2014-07-08 03:11:14 -04:00
# include "EmberPch.h"
# include "Renderer.h"
namespace EmberNs
{
2017-07-05 02:08:06 -04:00
/// <summary>
/// Constructor that allocates various pieces of memory.
/// </summary>
template < typename T , typename bucketT >
Renderer < T , bucketT > : : Renderer ( )
{
2017-07-22 16:43:35 -04:00
//Use a very large number regardless of the size of the output pixels. This should be sufficient granularity, even though
//it's technically less than the number of distinct values representable by a 32-bit float.
m_Csa . resize ( size_t ( CURVES_LENGTH ) ) ;
2018-09-15 06:11:12 -04:00
//Ensure the renderer at least has sane values for the camera upon startup.
//This is needed because due to timing/threading disconnects, the GUI can use the camera
//values before the render has started, which will lead to corrupt values.
Ember < T > ember ;
2018-09-27 20:02:34 -04:00
SetEmber ( ember , eProcessAction : : NOTHING , false ) ;
//Manually call these instead of passing true to SetEmber() because it would have created the spatial filter
//which we don't want to do until rendering starts (this is so the derived RendererCL can properly create the needed buffers).
ComputeBounds ( ) ;
ComputeQuality ( ) ;
ComputeCamera ( ) ;
2017-07-05 02:08:06 -04:00
}
2014-07-08 03:11:14 -04:00
/// <summary>
2014-10-14 11:53:15 -04:00
/// Non-virtual processing functions.
2014-07-08 03:11:14 -04:00
/// </summary>
/// <summary>
2014-10-14 11:53:15 -04:00
/// Add an ember to the end of the embers vector and reset the rendering process.
/// Reset the rendering process.
2014-07-08 03:11:14 -04:00
/// </summary>
2014-10-14 11:53:15 -04:00
/// <param name="ember">The ember to add</param>
2014-07-08 03:11:14 -04:00
template < typename T , typename bucketT >
2014-10-14 11:53:15 -04:00
void Renderer < T , bucketT > : : AddEmber ( Ember < T > & ember )
2014-07-08 03:11:14 -04:00
{
2014-10-14 11:53:15 -04:00
ChangeVal ( [ & ]
2014-07-08 03:11:14 -04:00
{
2014-10-14 11:53:15 -04:00
m_Embers . push_back ( ember ) ;
2014-09-10 01:41:26 -04:00
2014-10-14 11:53:15 -04:00
if ( m_Embers . size ( ) = = 1 )
m_Ember = m_Embers [ 0 ] ;
2015-12-31 19:00:36 -05:00
} , eProcessAction : : FULL_RENDER ) ;
2014-10-14 11:53:15 -04:00
}
/// <summary>
/// Set the m_Iterator member to point to the appropriate
/// iterator based on whether the ember currently being rendered
/// contains xaos.
/// After assigning, initialize the xform selection buffer.
/// </summary>
/// <returns>True if assignment and distribution initialization succeeded, else false.</returns>
template < typename T , typename bucketT >
bool Renderer < T , bucketT > : : AssignIterator ( )
{
//Setup iterator and distributions.
//Both iterator types were setup in the constructor (add more in the future if needed).
//So simply assign the pointer to the correct type and re-initialize its distributions
//based on the current ember.
if ( XaosPresent ( ) )
m_Iterator = m_XaosIterator . get ( ) ;
else
m_Iterator = m_StandardIterator . get ( ) ;
//Timing t;
return m_Iterator - > InitDistributions ( m_Ember ) ;
//t.Toc("Distrib creation");
}
/// <summary>
/// Virtual processing functions overriden from RendererBase.
/// </summary>
/// <summary>
/// Compute the bounds of the histogram and density filtering buffers.
/// These are affected by the final requested dimensions, spatial and density
/// filter sizes and supersampling.
/// </summary>
template < typename T , typename bucketT >
void Renderer < T , bucketT > : : ComputeBounds ( )
{
2016-03-28 21:49:10 -04:00
//Original did a lot of work to compute a gutter that changes size based on various parameters, which seems to be of no benefit.
//It also prevents the renderer from only performing filtering or final accum based on a filter parameter change, since that
//change may have changed the gutter.
//By using a fixed gutter, a filter change can be applied without fully restarting iteration.
m_GutterWidth = 10 * Supersample ( ) ; //Should be enough to fully accommodate most spatial and density filter widths.
2014-10-14 11:53:15 -04:00
m_SuperRasW = ( Supersample ( ) * FinalRasW ( ) ) + ( 2 * m_GutterWidth ) ;
m_SuperRasH = ( Supersample ( ) * FinalRasH ( ) ) + ( 2 * m_GutterWidth ) ;
m_SuperSize = m_SuperRasW * m_SuperRasH ;
2014-07-08 03:11:14 -04:00
}
2015-03-21 18:27:37 -04:00
/// <summary>
/// Compute the scale based on the zoom, then the quality based on the computed scale.
/// This must be called before ComputeCamera() which will use scale.
/// </summary>
template < typename T , typename bucketT >
void Renderer < T , bucketT > : : ComputeQuality ( )
{
--User changes
-Add new variations: bubbleT3D, crob, hexaplay3D, hexcrop, hexes, hexnix3D, loonie2, loonie3, nBlur, octapol and synth.
-Allow for pre/post versions of dc_bubble, dc_cylinder and dc_linear whereas before they were omitted.
-When saving a file with multiple embers in it, detect if time values are all the same and if so, start them at zero and increment by 1 for each ember.
-Allow for numerous quality increases to be coalesced into one. It will pick up at the end of the current render.
-Show selection highlight on variations tree in response to mouse hover. This makes it easier to see for which variation or param the current mouse wheel action will apply.
-Make default temporal samples be 100, whereas before it was 1000 which was overkill.
-Require the shift key to be held with delete for deleting an ember to prevent it from triggering when the user enters delete in the edit box.
-This wasn't otherwise fixable without writing a lot more code.
--Bug fixes
-EmberGenome was crashing when generating a sequence from a source file with more than 2 embers in it.
-EmberGenome was improperly handling the first frame of a merge after the last frame of the loop.
-These bugs were due to a previous commit. Revert parts of that commit.
-Prevent a zoom value of less than 0 when reading from xml.
-Slight optimization of the crescents, and mask variations, if the compiler wasn't doing it already.
-Unique file naming was broken because it was looking for _# and the default names ended with -#.
-Disallow renaming of an ember in the library tree to an empty string.
-Severe bug that prevented some variations from being read correctly from params generated outside this program.
-Severe OpenCL randomization bug. The first x coordinates of the first points in the first kernel call of the first ember of a render since the OpenCL renderer object was created were not random and were mostly -1.
-Severe bug when populating xform selection distributions that could sometimes cause a crash due to roundoff error. Fix by using double.
-Limit the max number of variations in a random ember to MAX_CL_VARS, which is 8. This ensures they'll look the same on CPU and GPU.
-Prevent user from saving stylesheet to default.qss, it's a special reserved filename.
--Code changes
-Generalize using the running sum output point inside of a variation for all cases: pre, reg and post.
-Allow for array variables in variations where the address of each element is stored in m_Params.
-Qualify all math functions with std::
-No longer use our own Clamp() in OpenCL, instead use the standard clamp().
-Redesign how functions are used in the variations OpenCL code.
-Add tests to EmberTester to verify some of the new functionality.
-Place more const and override qualifiers on functions where appropriate.
-Add a global rand with a lock to be used very sparingly.
-Use a map instead of a vector for bad param names in Xml parsing.
-Prefix affine interpolation mode defines with "AFFINE_" to make their purpose more clear.
-Allow for variations that change state during iteration by sending a separate copy of the ember to each rendering thread.
-Implement this same functionality with a local struct in OpenCL. It's members are the total of all variables that need to change state within an ember.
-Add Contains() function to Utils.h.
-EmberRender: print names of kernels being printed with --dump_kernel option.
-Clean up EmberTester to handle some of the recent changes.
-Fix various casts.
-Replace % 2 with & 1, even though the compiler was likely doing this already.
-Add new file Variations06.h to accommodate new variations.
-General cleanup.
2015-11-22 17:15:07 -05:00
m_Scale = std : : pow ( T ( 2.0 ) , Zoom ( ) ) ;
2015-03-21 18:27:37 -04:00
m_ScaledQuality = Quality ( ) * m_Scale * m_Scale ;
}
/// <summary>
/// Compute the camera.
/// This sets up the bounds of the cartesian plane that the raster bounds correspond to.
/// This must be called after ComputeBounds() which sets up the raster bounds.
/// </summary>
template < typename T , typename bucketT >
void Renderer < T , bucketT > : : ComputeCamera ( )
{
m_PixelsPerUnitX = PixelsPerUnit ( ) * m_Scale ;
m_PixelsPerUnitY = m_PixelsPerUnitX ;
m_PixelsPerUnitX / = PixelAspectRatio ( ) ;
T shift = 0 ;
T t0 = T ( m_GutterWidth ) / ( Supersample ( ) * m_PixelsPerUnitX ) ;
T t1 = T ( m_GutterWidth ) / ( Supersample ( ) * m_PixelsPerUnitY ) ;
//These go from ll to ur, moving from negative to positive.
m_LowerLeftX = CenterX ( ) - FinalRasW ( ) / m_PixelsPerUnitX / T ( 2.0 ) ;
m_LowerLeftY = CenterY ( ) - FinalRasH ( ) / m_PixelsPerUnitY / T ( 2.0 ) ;
m_UpperRightX = m_LowerLeftX + FinalRasW ( ) / m_PixelsPerUnitX ;
m_UpperRightY = m_LowerLeftY + FinalRasH ( ) / m_PixelsPerUnitY ;
T carLlX = m_LowerLeftX - t0 ;
T carLlY = m_LowerLeftY - t1 + shift ;
T carUrX = m_UpperRightX + t0 ;
T carUrY = m_UpperRightY + t1 + shift ;
m_RotMat . MakeID ( ) ;
2016-02-12 00:38:21 -05:00
m_RotMat . Rotate ( - Rotate ( ) * DEG_2_RAD_T ) ;
2015-03-21 18:27:37 -04:00
m_CarToRas . Init ( carLlX , carLlY , carUrX , carUrY , m_SuperRasW , m_SuperRasH , PixelAspectRatio ( ) ) ;
}
2014-07-08 03:11:14 -04:00
/// <summary>
/// Set the current ember.
/// This will also populate the vector of embers with a single element copy
/// of the ember passed in.
/// Temporal samples will be set to 1 since there's only a single ember.
/// </summary>
/// <param name="ember">The ember to assign</param>
/// <param name="action">The requested process action. Note that it's critical the user supply the proper value here.
2015-12-31 19:00:36 -05:00
/// For example: Changing dimensions without setting action to eProcessAction::FULL_RENDER will crash the program.
2014-07-08 03:11:14 -04:00
/// However, changing only the brightness and setting action to ACCUM_ONLY is perfectly fine.
2017-05-12 18:31:48 -04:00
/// <param name="prep">Whether to also compute bounds, camera, filters etc. This is useful when other code outside of this needs these values
/// before the render actually starts. Default: false.</param>
2014-07-08 03:11:14 -04:00
/// </param>
template < typename T , typename bucketT >
2017-05-12 18:31:48 -04:00
void Renderer < T , bucketT > : : SetEmber ( const Ember < T > & ember , eProcessAction action , bool prep )
2014-07-08 03:11:14 -04:00
{
ChangeVal ( [ & ]
2014-09-10 01:41:26 -04:00
{
2014-07-08 03:11:14 -04:00
m_Embers . clear ( ) ;
m_Embers . push_back ( ember ) ;
m_Embers [ 0 ] . m_TemporalSamples = 1 ; //Set temporal samples here to 1 because using the real value only makes sense when using a vector of Embers for animation.
m_Ember = m_Embers [ 0 ] ;
2016-04-03 21:55:12 -04:00
m_EmbersP = & m_Embers ;
2014-07-08 03:11:14 -04:00
} , action ) ;
2017-05-12 18:31:48 -04:00
if ( prep )
{
bool b = false ;
CreateSpatialFilter ( b ) ;
CreateTemporalFilter ( b ) ;
ComputeBounds ( ) ;
ComputeQuality ( ) ;
ComputeCamera ( ) ;
}
2014-07-08 03:11:14 -04:00
}
/// <summary>
2016-04-03 21:55:12 -04:00
/// Copy the embers in the passed in container to the internal vector of embers
/// and set the m_Ember member to a copy of the first element.
2014-07-08 03:11:14 -04:00
/// Reset the rendering process.
/// </summary>
2016-04-03 21:55:12 -04:00
/// <param name="embers">The container of embers to be copied</param>
2014-07-08 03:11:14 -04:00
template < typename T , typename bucketT >
2016-04-03 21:55:12 -04:00
template < typename C >
void Renderer < T , bucketT > : : SetEmber ( const C & embers )
2014-07-08 03:11:14 -04:00
{
ChangeVal ( [ & ]
{
2016-04-03 21:55:12 -04:00
CopyCont ( m_Embers , embers ) ;
m_EmbersP = & m_Embers ;
2014-07-08 03:11:14 -04:00
if ( ! m_Embers . empty ( ) )
m_Ember = m_Embers [ 0 ] ;
2015-12-31 19:00:36 -05:00
} , eProcessAction : : FULL_RENDER ) ;
2014-07-08 03:11:14 -04:00
}
2016-04-03 21:55:12 -04:00
/// <summary>
/// Move the embers in the passed in vector to the internal vector of embers
/// and set the m_Ember member to a copy of the first element.
/// Reset the rendering process.
/// This is preferred over SetEmber when the size of embers is large and/or
/// the caller no longer needs to use the argument after this function returns.
/// </summary>
/// <param name="embers">The vector of embers to be moved</param>
template < typename T , typename bucketT >
void Renderer < T , bucketT > : : MoveEmbers ( vector < Ember < T > > & embers )
{
ChangeVal ( [ & ]
{
m_Embers = std : : move ( embers ) ;
m_EmbersP = & m_Embers ;
if ( ! m_Embers . empty ( ) )
m_Ember = m_Embers [ 0 ] ;
} , eProcessAction : : FULL_RENDER ) ;
}
template < typename T , typename bucketT >
void Renderer < T , bucketT > : : SetExternalEmbersPointer ( vector < Ember < T > > * embers )
{
ChangeVal ( [ & ]
{
m_Embers . clear ( ) ;
m_EmbersP = embers ;
if ( ! m_EmbersP - > empty ( ) )
m_Ember = ( * m_EmbersP ) [ 0 ] ;
} , eProcessAction : : FULL_RENDER ) ;
}
2014-07-08 03:11:14 -04:00
/// <summary>
2014-10-14 11:53:15 -04:00
/// Create the density filter if the current filter parameters differ
/// from the last density filter created.
/// The filter will be deleted if the max DE radius is 0, in which case regular
/// log scale filtering will be used.
2014-07-08 03:11:14 -04:00
/// </summary>
2014-10-14 11:53:15 -04:00
/// <param name="newAlloc">True if a new filter instance was created, else false.</param>
/// <returns>True if the filter is not nullptr (whether a new one was created or not) or if max rad is 0, else false.</returns>
2014-07-08 03:11:14 -04:00
template < typename T , typename bucketT >
2014-10-14 11:53:15 -04:00
bool Renderer < T , bucketT > : : CreateDEFilter ( bool & newAlloc )
2014-07-08 03:11:14 -04:00
{
2014-10-14 11:53:15 -04:00
//If they wanted DE, create it if needed, else clear the last DE filter which means we'll do regular log filtering after iters are done.
newAlloc = false ;
if ( m_Ember . m_MaxRadDE > 0 )
2014-07-08 03:11:14 -04:00
{
2014-10-14 11:53:15 -04:00
//Use intelligent testing so it isn't created every time a new ember is passed in.
if ( ( ! m_DensityFilter . get ( ) ) | |
2015-12-31 19:00:36 -05:00
( m_Ember . m_MinRadDE ! = m_DensityFilter - > MinRad ( ) ) | |
( m_Ember . m_MaxRadDE ! = m_DensityFilter - > MaxRad ( ) ) | |
( m_Ember . m_CurveDE ! = m_DensityFilter - > Curve ( ) ) | |
( m_Ember . m_Supersample ! = m_DensityFilter - > Supersample ( ) ) )
2014-10-14 11:53:15 -04:00
{
2016-04-03 21:55:12 -04:00
m_DensityFilter = make_unique < DensityFilter < bucketT > > ( bucketT ( m_Ember . m_MinRadDE ) , bucketT ( m_Ember . m_MaxRadDE ) , bucketT ( m_Ember . m_CurveDE ) , m_Ember . m_Supersample ) ;
2014-10-14 11:53:15 -04:00
newAlloc = true ;
}
2014-07-08 03:11:14 -04:00
2014-10-14 11:53:15 -04:00
if ( newAlloc )
{
if ( ! m_DensityFilter . get ( ) ) { return false ; } //Did object creation succeed?
2015-12-31 19:00:36 -05:00
2014-10-14 11:53:15 -04:00
if ( ! m_DensityFilter - > Create ( ) ) { return false ; } //Object creation succeeded, did filter creation succeed?
}
2015-12-31 19:00:36 -05:00
else if ( ! m_DensityFilter - > Valid ( ) ) { return false ; } //Previously created, are values ok?
2014-10-14 11:53:15 -04:00
}
else
{
m_DensityFilter . reset ( ) ; //They want to do log filtering. Return true because even though the filter is being deleted, nothing went wrong.
}
return true ;
}
/// <summary>
/// Create the spatial filter if the current filter parameters differ
/// from the last spatial filter created.
/// </summary>
/// <param name="newAlloc">True if a new filter instance was created, else false.</param>
/// <returns>True if the filter is not nullptr (whether a new one was created or not), else false.</returns>
template < typename T , typename bucketT >
bool Renderer < T , bucketT > : : CreateSpatialFilter ( bool & newAlloc )
{
newAlloc = false ;
//Use intelligent testing so it isn't created every time a new ember is passed in.
if ( ( ! m_SpatialFilter . get ( ) ) | |
2015-12-31 19:00:36 -05:00
( m_Ember . m_SpatialFilterType ! = m_SpatialFilter - > FilterType ( ) ) | |
( m_Ember . m_SpatialFilterRadius ! = m_SpatialFilter - > FilterRadius ( ) ) | |
( m_Ember . m_Supersample ! = m_SpatialFilter - > Supersample ( ) ) | |
( m_PixelAspectRatio ! = m_SpatialFilter - > PixelAspectRatio ( ) ) )
2014-10-14 11:53:15 -04:00
{
2015-08-10 23:10:23 -04:00
m_SpatialFilter = unique_ptr < SpatialFilter < bucketT > > (
2015-12-31 19:00:36 -05:00
SpatialFilterCreator < bucketT > : : Create ( m_Ember . m_SpatialFilterType , bucketT ( m_Ember . m_SpatialFilterRadius ) , m_Ember . m_Supersample , bucketT ( m_PixelAspectRatio ) ) ) ;
2014-10-17 02:05:08 -04:00
m_Ember . m_SpatialFilterRadius = m_SpatialFilter - > FilterRadius ( ) ; //It may have been changed internally if it was too small, so ensure they're synced.
2014-10-14 11:53:15 -04:00
newAlloc = true ;
}
return m_SpatialFilter . get ( ) ! = nullptr ;
2014-07-08 03:11:14 -04:00
}
/// <summary>
/// Create the temporal filter if the current filter parameters differ
/// from the last temporal filter created.
/// </summary>
/// <param name="newAlloc">True if a new filter instance was created, else false.</param>
2014-09-10 01:41:26 -04:00
/// <returns>True if the filter is not nullptr (whether a new one was created or not), else false.</returns>
2014-07-08 03:11:14 -04:00
template < typename T , typename bucketT >
bool Renderer < T , bucketT > : : CreateTemporalFilter ( bool & newAlloc )
{
newAlloc = false ;
//Use intelligent testing so it isn't created every time a new ember is passed in.
2014-08-03 19:16:10 -04:00
if ( ( ! m_TemporalFilter . get ( ) ) | |
2015-12-31 19:00:36 -05:00
( m_Ember . m_TemporalSamples ! = m_TemporalFilter - > TemporalSamples ( ) ) | |
( m_Ember . m_TemporalFilterType ! = m_TemporalFilter - > FilterType ( ) ) | |
( m_Ember . m_TemporalFilterWidth ! = m_TemporalFilter - > FilterWidth ( ) ) | |
( m_Ember . m_TemporalFilterExp ! = m_TemporalFilter - > FilterExp ( ) ) )
2014-07-08 03:11:14 -04:00
{
2014-09-10 01:41:26 -04:00
m_TemporalFilter = unique_ptr < TemporalFilter < T > > (
2015-12-31 19:00:36 -05:00
TemporalFilterCreator < T > : : Create ( m_Ember . m_TemporalFilterType , m_Ember . m_TemporalSamples , m_Ember . m_TemporalFilterWidth , m_Ember . m_TemporalFilterExp ) ) ;
2014-07-08 03:11:14 -04:00
newAlloc = true ;
}
2014-09-10 01:41:26 -04:00
return m_TemporalFilter . get ( ) ! = nullptr ;
2014-07-08 03:11:14 -04:00
}
/// <summary>
/// The main render loop. This is the core of the algorithm.
/// The processing steps are: Iterating, density filtering, final accumulation.
/// Various functions in it are virtual so they will resolve
/// to whatever overrides are provided in derived classes. This
/// future-proofs the algorithm for GPU-based renderers.
/// If the caller calls Abort() at any time, or the progress function returns 0,
/// the entire rendering process will exit as soon as it can.
2014-11-03 02:16:34 -05:00
/// The concept of passes from flam3 has been removed as it was never used.
2014-07-08 03:11:14 -04:00
/// The loop structure is:
/// {
2014-11-03 02:16:34 -05:00
/// Temporal Samples (Default 1 for single image)
2014-07-08 03:11:14 -04:00
/// {
2014-11-03 02:16:34 -05:00
/// Iterate (Either to completion or to a specified number of iterations)
2014-07-08 03:11:14 -04:00
/// {
/// }
/// }
///
/// Density filtering (Basic log, or full density estimation)
/// Final accumulation (Color correction and spatial filtering)
/// }
/// This loop structure has admittedly been severely butchered from what
/// flam3 did. The reason is that it was made to support interactive rendering
/// that can exit the process and pick up where it left off in response to the
/// user changing values in a fractal flame GUI editor.
/// To achieve this, each step in the rendering process is given an enumeration state
/// as well as a goto label. This allows the renderer to pick up in the state it left
/// off in if no changes prohibiting that have been made.
/// It also allows for the bare minimum amount of processing needed to complete the requested
/// action. For example, if the process has completed and the user only adjusts the brightness
/// of the last rendered ember then there is no need to perform the entire iteration process
/// over again. Rather, only final accumulation is needed.
/// </summary>
/// <param name="finalImage">Storage for the final image. It will be allocated if needed.</param>
/// <param name="time">The time if animating, else ignored.</param>
/// <param name="subBatchCountOverride">Run a specified number of sub batches. Default: 0, meaning run to completion.</param>
/// <param name="forceOutput">True to force rendering a complete image even if iterating is not complete, else don't. Default: false.</param>
/// <param name="finalOffset">Offset in finalImage to store the pixels to. Default: 0.</param>
/// <returns>True if nothing went wrong, else false.</returns>
template < typename T , typename bucketT >
2017-07-22 16:43:35 -04:00
eRenderStatus Renderer < T , bucketT > : : Run ( vector < v4F > & finalImage , double time , size_t subBatchCountOverride , bool forceOutput , size_t finalOffset )
2014-07-08 03:11:14 -04:00
{
m_InRender = true ;
EnterRender ( ) ;
m_Abort = false ;
2015-12-31 19:00:36 -05:00
bool filterAndAccumOnly = m_ProcessAction = = eProcessAction : : FILTER_AND_ACCUM ;
bool accumOnly = m_ProcessAction = = eProcessAction : : ACCUM_ONLY ;
bool resume = m_ProcessState ! = eProcessState : : NONE ;
2014-07-08 03:11:14 -04:00
bool newFilterAlloc ;
2017-07-05 02:08:06 -04:00
size_t temporalSample = 0 ;
2014-09-01 00:25:15 -04:00
T deTime ;
2015-12-31 19:00:36 -05:00
auto success = eRenderStatus : : RENDER_OK ;
2014-07-08 03:11:14 -04:00
//Reset timers and progress percent if: Beginning anew or only filtering and/or accumulating.
if ( ! resume | | accumOnly | | filterAndAccumOnly )
{
if ( ! resume ) //Only set this if it's the first run through.
2015-12-31 19:00:36 -05:00
m_ProcessState = eProcessState : : ITER_STARTED ;
2014-07-08 03:11:14 -04:00
m_RenderTimer . Tic ( ) ;
m_ProgressTimer . Tic ( ) ;
}
if ( ! resume ) //Beginning, reset everything.
{
m_LastTemporalSample = 0 ;
m_LastIter = 0 ;
m_LastIterPercent = 0 ;
2014-08-06 00:50:52 -04:00
m_Stats . Clear ( ) ;
2014-07-08 03:11:14 -04:00
m_Gamma = 0 ;
m_Vibrancy = 0 ; //Accumulate these after each temporal sample.
m_VibGamCount = 0 ;
2015-03-21 18:27:37 -04:00
m_CurvesSet = false ;
2014-07-08 03:11:14 -04:00
m_Background . Clear ( ) ;
}
//User requested an increase in quality after finishing.
2015-12-31 19:00:36 -05:00
else if ( m_ProcessState = = eProcessState : : ITER_STARTED & & m_ProcessAction = = eProcessAction : : KEEP_ITERATING & & TemporalSamples ( ) = = 1 )
2014-07-08 03:11:14 -04:00
{
m_LastTemporalSample = 0 ;
m_LastIter = m_Stats . m_Iters ;
m_LastIterPercent = 0 ; //Might skip a progress update, but shouldn't matter.
m_Gamma = 0 ;
m_Vibrancy = 0 ;
m_VibGamCount = 0 ;
m_Background . Clear ( ) ;
2015-03-21 18:27:37 -04:00
ComputeQuality ( ) ; //Must recompute quality when doing a quality increase.
2014-07-08 03:11:14 -04:00
}
//Make sure values are within valid range.
2014-10-15 11:19:59 -04:00
ClampGteRef ( m_Ember . m_Supersample , size_t ( 1 ) ) ;
2014-07-08 03:11:14 -04:00
//Make sure to get most recent update since loop won't be entered to call Interp().
//Vib, gam and background are normally summed for each temporal sample. However if iteration is skipped, make sure to get the latest.
if ( ( filterAndAccumOnly | | accumOnly ) & & TemporalSamples ( ) = = 1 ) //Disallow jumping when temporal samples > 1.
{
2016-04-03 21:55:12 -04:00
m_Ember = ( * m_EmbersP ) [ 0 ] ;
2015-08-10 23:10:23 -04:00
m_Vibrancy = Vibrancy ( ) ;
m_Gamma = Gamma ( ) ;
2014-07-08 03:11:14 -04:00
m_Background = m_Ember . m_Background ;
2014-09-10 01:41:26 -04:00
2014-07-08 03:11:14 -04:00
if ( filterAndAccumOnly )
goto FilterAndAccum ;
2014-09-10 01:41:26 -04:00
2014-07-08 03:11:14 -04:00
if ( accumOnly )
goto AccumOnly ;
}
//it.Tic();
//Interpolate.
2016-04-03 21:55:12 -04:00
if ( m_EmbersP - > size ( ) > 1 )
2016-04-23 12:02:09 -04:00
m_Interpolater . Interpolate ( * m_EmbersP , T ( time ) , 0 , m_Ember ) ;
2015-12-31 19:00:36 -05:00
2014-07-08 03:11:14 -04:00
//it.Toc("Interp 1");
//Save only for palette insertion.
2016-04-11 21:15:14 -04:00
if ( m_InsertPalette )
2014-07-08 03:11:14 -04:00
m_TempEmber = m_Ember ;
2016-03-28 21:49:10 -04:00
if ( ! resume ) //Only need to create this when starting a new render.
{
CreateSpatialFilter ( newFilterAlloc ) ; //Will be checked and recreated again if necessary right before final output.
CreateTemporalFilter ( newFilterAlloc ) ; //But create here just to ensure allocation succeeded.
ComputeBounds ( ) ;
}
2014-07-08 03:11:14 -04:00
2014-09-10 01:41:26 -04:00
if ( m_SpatialFilter . get ( ) = = nullptr | | m_TemporalFilter . get ( ) = = nullptr )
2014-07-08 03:11:14 -04:00
{
2015-12-10 23:19:41 -05:00
AddToReport ( " Spatial and temporal filter allocations failed, aborting. \n " ) ;
2015-12-31 19:00:36 -05:00
success = eRenderStatus : : RENDER_ERROR ;
2014-07-08 03:11:14 -04:00
goto Finish ;
}
if ( ! resume & & ! Alloc ( ) )
{
2015-12-10 23:19:41 -05:00
AddToReport ( " Histogram, accumulator and samples buffer allocations failed, aborting. \n " ) ;
2015-12-31 19:00:36 -05:00
success = eRenderStatus : : RENDER_ERROR ;
2014-07-08 03:11:14 -04:00
goto Finish ;
}
if ( ! resume )
2017-08-28 00:24:33 -04:00
{
if ( ! ResetBuckets ( true , false ) ) //Only reset hist here and do accum when needed later on.
{
success = eRenderStatus : : RENDER_ERROR ;
goto Finish ;
}
}
2014-07-08 03:11:14 -04:00
2016-03-28 21:49:10 -04:00
deTime = T ( time ) + * m_TemporalFilter - > Deltas ( ) ;
2014-11-03 02:16:34 -05:00
//Interpolate and get an ember for DE purposes.
//Additional interpolation will be done in the temporal samples loop.
//it.Tic();
2016-04-03 21:55:12 -04:00
if ( m_EmbersP - > size ( ) > 1 )
2016-04-23 12:02:09 -04:00
m_Interpolater . Interpolate ( * m_EmbersP , deTime , 0 , m_Ember ) ;
2014-11-03 02:16:34 -05:00
2015-12-31 19:00:36 -05:00
//it.Toc("Interp 2");
2015-03-21 18:27:37 -04:00
ClampGteRef < T > ( m_Ember . m_MinRadDE , 0 ) ;
ClampGteRef < T > ( m_Ember . m_MaxRadDE , 0 ) ;
ClampGteRef < T > ( m_Ember . m_MaxRadDE , m_Ember . m_MinRadDE ) ;
2014-11-03 02:16:34 -05:00
2016-03-28 21:49:10 -04:00
if ( ! CreateDEFilter ( newFilterAlloc ) ) //Will be checked and recreated again if necessary right before density filtering.
2014-07-08 03:11:14 -04:00
{
2015-12-10 23:19:41 -05:00
AddToReport ( " Density filter creation failed, aborting. \n " ) ;
2015-12-31 19:00:36 -05:00
success = eRenderStatus : : RENDER_ERROR ;
2014-11-03 02:16:34 -05:00
goto Finish ;
}
//Temporal samples, loop 1.
temporalSample = resume ? m_LastTemporalSample : 0 ;
2015-12-31 19:00:36 -05:00
2014-11-03 02:16:34 -05:00
for ( ; ( temporalSample < TemporalSamples ( ) ) & & ! m_Abort ; )
{
T colorScalar = m_TemporalFilter - > Filter ( ) [ temporalSample ] ;
T temporalTime = T ( time ) + m_TemporalFilter - > Deltas ( ) [ temporalSample ] ;
2014-07-08 03:11:14 -04:00
2014-11-03 02:16:34 -05:00
//Interpolate again.
2014-07-08 03:11:14 -04:00
//it.Tic();
2016-04-03 21:55:12 -04:00
if ( TemporalSamples ( ) > 1 & & m_EmbersP - > size ( ) > 1 )
2016-04-23 12:02:09 -04:00
m_Interpolater . Interpolate ( * m_EmbersP , temporalTime , 0 , m_Ember ) ; //This will perform all necessary precalcs via the ember/xform/variation assignment operators.
2014-07-08 03:11:14 -04:00
2014-11-03 02:16:34 -05:00
//it.Toc("Interp 3");
2014-07-08 03:11:14 -04:00
2014-11-03 02:16:34 -05:00
if ( ! resume & & ! AssignIterator ( ) )
2014-07-08 03:11:14 -04:00
{
2015-12-10 23:19:41 -05:00
AddToReport ( " Iterator assignment failed, aborting. \n " ) ;
2015-12-31 19:00:36 -05:00
success = eRenderStatus : : RENDER_ERROR ;
2014-07-08 03:11:14 -04:00
goto Finish ;
}
--User changes
-Add new variations: bubbleT3D, crob, hexaplay3D, hexcrop, hexes, hexnix3D, loonie2, loonie3, nBlur, octapol and synth.
-Allow for pre/post versions of dc_bubble, dc_cylinder and dc_linear whereas before they were omitted.
-When saving a file with multiple embers in it, detect if time values are all the same and if so, start them at zero and increment by 1 for each ember.
-Allow for numerous quality increases to be coalesced into one. It will pick up at the end of the current render.
-Show selection highlight on variations tree in response to mouse hover. This makes it easier to see for which variation or param the current mouse wheel action will apply.
-Make default temporal samples be 100, whereas before it was 1000 which was overkill.
-Require the shift key to be held with delete for deleting an ember to prevent it from triggering when the user enters delete in the edit box.
-This wasn't otherwise fixable without writing a lot more code.
--Bug fixes
-EmberGenome was crashing when generating a sequence from a source file with more than 2 embers in it.
-EmberGenome was improperly handling the first frame of a merge after the last frame of the loop.
-These bugs were due to a previous commit. Revert parts of that commit.
-Prevent a zoom value of less than 0 when reading from xml.
-Slight optimization of the crescents, and mask variations, if the compiler wasn't doing it already.
-Unique file naming was broken because it was looking for _# and the default names ended with -#.
-Disallow renaming of an ember in the library tree to an empty string.
-Severe bug that prevented some variations from being read correctly from params generated outside this program.
-Severe OpenCL randomization bug. The first x coordinates of the first points in the first kernel call of the first ember of a render since the OpenCL renderer object was created were not random and were mostly -1.
-Severe bug when populating xform selection distributions that could sometimes cause a crash due to roundoff error. Fix by using double.
-Limit the max number of variations in a random ember to MAX_CL_VARS, which is 8. This ensures they'll look the same on CPU and GPU.
-Prevent user from saving stylesheet to default.qss, it's a special reserved filename.
--Code changes
-Generalize using the running sum output point inside of a variation for all cases: pre, reg and post.
-Allow for array variables in variations where the address of each element is stored in m_Params.
-Qualify all math functions with std::
-No longer use our own Clamp() in OpenCL, instead use the standard clamp().
-Redesign how functions are used in the variations OpenCL code.
-Add tests to EmberTester to verify some of the new functionality.
-Place more const and override qualifiers on functions where appropriate.
-Add a global rand with a lock to be used very sparingly.
-Use a map instead of a vector for bad param names in Xml parsing.
-Prefix affine interpolation mode defines with "AFFINE_" to make their purpose more clear.
-Allow for variations that change state during iteration by sending a separate copy of the ember to each rendering thread.
-Implement this same functionality with a local struct in OpenCL. It's members are the total of all variables that need to change state within an ember.
-Add Contains() function to Utils.h.
-EmberRender: print names of kernels being printed with --dump_kernel option.
-Clean up EmberTester to handle some of the recent changes.
-Fix various casts.
-Replace % 2 with & 1, even though the compiler was likely doing this already.
-Add new file Variations06.h to accommodate new variations.
-General cleanup.
2015-11-22 17:15:07 -05:00
//Do this every iteration for an animation, or else do it once for a single image.
2015-03-21 18:27:37 -04:00
if ( TemporalSamples ( ) > 1 | | ! resume )
{
ComputeQuality ( ) ;
ComputeCamera ( ) ;
MakeDmap ( colorScalar ) ; //For each temporal sample, the palette m_Dmap needs to be re-created with color scalar. 1 if no temporal samples.
}
2014-10-27 17:21:06 -04:00
2014-11-03 02:16:34 -05:00
//The actual number of times to iterate. Each thread will get (totalIters / ThreadCount) iters to do.
2015-03-21 18:27:37 -04:00
//This is based on zoom and scale calculated in ComputeQuality().
2014-11-03 02:16:34 -05:00
//Note that the iter count is based on the final image dimensions, and not the super sampled dimensions.
size_t itersPerTemporalSample = ItersPerTemporalSample ( ) ; //The total number of iterations for this temporal sample without overrides.
size_t sampleItersToDo ; //The number of iterations to actually do in this sample, considering overrides.
2014-07-08 03:11:14 -04:00
2014-11-03 02:16:34 -05:00
if ( subBatchCountOverride > 0 )
sampleItersToDo = subBatchCountOverride * SubBatchSize ( ) * ThreadCount ( ) ; //Run a specific number of sub batches.
else
sampleItersToDo = itersPerTemporalSample ; //Run as many iters as specified to complete this temporal sample.
2014-09-01 00:25:15 -04:00
2015-03-21 18:27:37 -04:00
sampleItersToDo = std : : min < size_t > ( sampleItersToDo , itersPerTemporalSample - m_LastIter ) ;
2014-11-03 02:16:34 -05:00
EmberStats stats = Iterate ( sampleItersToDo , temporalSample ) ; //The heavy work is done here.
2014-07-08 03:11:14 -04:00
2018-10-05 22:50:38 -04:00
//Abort does not indicate an error, it just means the process was interrupted, most likely by the user on the GUI.
if ( m_Abort )
2014-11-03 02:16:34 -05:00
{
2018-10-05 22:50:38 -04:00
success = eRenderStatus : : RENDER_ABORT ;
2014-11-03 02:16:34 -05:00
goto Finish ;
}
2014-07-08 03:11:14 -04:00
2018-10-05 22:50:38 -04:00
//If no iters were executed, something went catastrophically wrong.
if ( ! stats . m_Success & & stats . m_Iters = = 0 )
2014-11-03 02:16:34 -05:00
{
2018-10-05 22:50:38 -04:00
AddToReport ( " Zero iterations ran, rendering failed, aborting. \n " ) ;
success = eRenderStatus : : RENDER_ERROR ;
Abort ( ) ;
2014-11-03 02:16:34 -05:00
goto Finish ;
}
2014-07-08 03:11:14 -04:00
2014-11-03 02:16:34 -05:00
//Accumulate stats whether this batch ran to completion or exited prematurely.
m_LastIter + = stats . m_Iters ; //Sum of iter count of all threads, reset each temporal sample.
m_Stats . m_Iters + = stats . m_Iters ; //Sum of iter count of all threads, cumulative from beginning to end.
m_Stats . m_Badvals + = stats . m_Badvals ;
m_Stats . m_IterMs + = stats . m_IterMs ;
2014-07-08 03:11:14 -04:00
2014-11-03 02:16:34 -05:00
//After each temporal sample, accumulate these.
//Allow for incremental rendering by only taking action if the iter loop for this temporal sample is completely done.
if ( m_LastIter > = itersPerTemporalSample )
{
2015-08-10 23:10:23 -04:00
m_Vibrancy + = Vibrancy ( ) ;
m_Gamma + = Gamma ( ) ;
m_Background . r + = bucketT ( m_Ember . m_Background . r ) ;
m_Background . g + = bucketT ( m_Ember . m_Background . g ) ;
m_Background . b + = bucketT ( m_Ember . m_Background . b ) ;
2014-11-03 02:16:34 -05:00
m_VibGamCount + + ;
m_LastIter = 0 ;
temporalSample + + ;
}
2014-07-08 03:11:14 -04:00
2014-11-03 02:16:34 -05:00
m_LastTemporalSample = temporalSample ;
2014-07-08 03:11:14 -04:00
2014-11-03 02:16:34 -05:00
if ( subBatchCountOverride > 0 ) //Don't keep going through this loop if only doing an incremental render.
break ;
} //Temporal samples.
2014-07-08 03:11:14 -04:00
2014-11-03 02:16:34 -05:00
//If we've completed all temporal samples, then it was a complete render, so report progress.
if ( temporalSample > = TemporalSamples ( ) )
{
2015-12-31 19:00:36 -05:00
m_ProcessState = eProcessState : : ITER_DONE ;
2014-07-08 03:11:14 -04:00
2014-11-03 02:16:34 -05:00
if ( m_Callback & & ! m_Callback - > ProgressFunc ( m_Ember , m_ProgressParameter , 100.0 , 0 , 0 ) )
2014-07-08 03:11:14 -04:00
{
2014-11-03 02:16:34 -05:00
Abort ( ) ;
2015-12-31 19:00:36 -05:00
success = eRenderStatus : : RENDER_ABORT ;
2014-11-03 02:16:34 -05:00
goto Finish ;
2014-07-08 03:11:14 -04:00
}
2014-11-03 02:16:34 -05:00
}
2014-07-08 03:11:14 -04:00
FilterAndAccum :
2015-12-31 19:00:36 -05:00
2014-11-03 02:16:34 -05:00
if ( filterAndAccumOnly | | temporalSample > = TemporalSamples ( ) | | forceOutput )
{
//t.Toc("Iterating and accumulating");
//Compute k1 and k2.
2015-12-31 19:00:36 -05:00
auto fullRun = eRenderStatus : : RENDER_OK ; //Whether density filtering was run to completion without aborting prematurely or triggering an error.
2014-11-03 02:16:34 -05:00
T area = FinalRasW ( ) * FinalRasH ( ) / ( m_PixelsPerUnitX * m_PixelsPerUnitY ) ; //Need to use temps from field if ever implemented.
2015-08-10 23:10:23 -04:00
m_K1 = bucketT ( ( Brightness ( ) * 268 ) / 256 ) ;
2014-07-08 03:11:14 -04:00
2014-11-03 02:16:34 -05:00
//When doing an interactive render, force output early on in the render process, before all iterations are done.
//This presents a problem with the normal calculation of K2 since it relies on the quality value; it will scale the colors
//to be very dark. Correct it by pretending the number of iters done is the exact quality desired and then scale according to that.
if ( forceOutput )
{
2014-12-07 02:51:44 -05:00
T quality = ( T ( m_Stats . m_Iters ) / T ( FinalDimensions ( ) ) ) * ( m_Scale * m_Scale ) ;
2015-08-10 23:10:23 -04:00
m_K2 = bucketT ( ( Supersample ( ) * Supersample ( ) ) / ( area * quality * m_TemporalFilter - > SumFilt ( ) ) ) ;
2014-11-03 02:16:34 -05:00
}
else
2015-08-10 23:10:23 -04:00
m_K2 = bucketT ( ( Supersample ( ) * Supersample ( ) ) / ( area * m_ScaledQuality * m_TemporalFilter - > SumFilt ( ) ) ) ;
2014-07-08 03:11:14 -04:00
2017-08-28 00:24:33 -04:00
if ( ! ResetBuckets ( false , true ) ) //Only the histogram was reset above, now reset the density filtering buffer.
{
success = eRenderStatus : : RENDER_ERROR ;
goto Finish ;
}
2014-11-03 02:16:34 -05:00
//t.Tic();
2016-03-28 21:49:10 -04:00
//Make sure a density filter was created with the latest values.
ClampGteRef < T > ( m_Ember . m_MinRadDE , 0 ) ;
ClampGteRef < T > ( m_Ember . m_MaxRadDE , 0 ) ;
ClampGteRef < T > ( m_Ember . m_MaxRadDE , m_Ember . m_MinRadDE ) ;
CreateDEFilter ( newFilterAlloc ) ;
2014-07-08 03:11:14 -04:00
2014-11-03 02:16:34 -05:00
//Apply appropriate filter if iterating is complete.
if ( filterAndAccumOnly | | temporalSample > = TemporalSamples ( ) )
{
--User changes
-Add new variations: bubbleT3D, crob, hexaplay3D, hexcrop, hexes, hexnix3D, loonie2, loonie3, nBlur, octapol and synth.
-Allow for pre/post versions of dc_bubble, dc_cylinder and dc_linear whereas before they were omitted.
-When saving a file with multiple embers in it, detect if time values are all the same and if so, start them at zero and increment by 1 for each ember.
-Allow for numerous quality increases to be coalesced into one. It will pick up at the end of the current render.
-Show selection highlight on variations tree in response to mouse hover. This makes it easier to see for which variation or param the current mouse wheel action will apply.
-Make default temporal samples be 100, whereas before it was 1000 which was overkill.
-Require the shift key to be held with delete for deleting an ember to prevent it from triggering when the user enters delete in the edit box.
-This wasn't otherwise fixable without writing a lot more code.
--Bug fixes
-EmberGenome was crashing when generating a sequence from a source file with more than 2 embers in it.
-EmberGenome was improperly handling the first frame of a merge after the last frame of the loop.
-These bugs were due to a previous commit. Revert parts of that commit.
-Prevent a zoom value of less than 0 when reading from xml.
-Slight optimization of the crescents, and mask variations, if the compiler wasn't doing it already.
-Unique file naming was broken because it was looking for _# and the default names ended with -#.
-Disallow renaming of an ember in the library tree to an empty string.
-Severe bug that prevented some variations from being read correctly from params generated outside this program.
-Severe OpenCL randomization bug. The first x coordinates of the first points in the first kernel call of the first ember of a render since the OpenCL renderer object was created were not random and were mostly -1.
-Severe bug when populating xform selection distributions that could sometimes cause a crash due to roundoff error. Fix by using double.
-Limit the max number of variations in a random ember to MAX_CL_VARS, which is 8. This ensures they'll look the same on CPU and GPU.
-Prevent user from saving stylesheet to default.qss, it's a special reserved filename.
--Code changes
-Generalize using the running sum output point inside of a variation for all cases: pre, reg and post.
-Allow for array variables in variations where the address of each element is stored in m_Params.
-Qualify all math functions with std::
-No longer use our own Clamp() in OpenCL, instead use the standard clamp().
-Redesign how functions are used in the variations OpenCL code.
-Add tests to EmberTester to verify some of the new functionality.
-Place more const and override qualifiers on functions where appropriate.
-Add a global rand with a lock to be used very sparingly.
-Use a map instead of a vector for bad param names in Xml parsing.
-Prefix affine interpolation mode defines with "AFFINE_" to make their purpose more clear.
-Allow for variations that change state during iteration by sending a separate copy of the ember to each rendering thread.
-Implement this same functionality with a local struct in OpenCL. It's members are the total of all variables that need to change state within an ember.
-Add Contains() function to Utils.h.
-EmberRender: print names of kernels being printed with --dump_kernel option.
-Clean up EmberTester to handle some of the recent changes.
-Fix various casts.
-Replace % 2 with & 1, even though the compiler was likely doing this already.
-Add new file Variations06.h to accommodate new variations.
-General cleanup.
2015-11-22 17:15:07 -05:00
fullRun = m_DensityFilter . get ( ) ? GaussianDensityFilter ( ) : LogScaleDensityFilter ( forceOutput ) ;
2014-11-03 02:16:34 -05:00
}
else
{
//Apply requested filter for a forced output during interactive rendering.
2015-12-31 19:00:36 -05:00
if ( m_DensityFilter . get ( ) & & m_InteractiveFilter = = eInteractiveFilter : : FILTER_DE )
2014-11-03 02:16:34 -05:00
fullRun = GaussianDensityFilter ( ) ;
2015-12-31 19:00:36 -05:00
else if ( ! m_DensityFilter . get ( ) | | m_InteractiveFilter = = eInteractiveFilter : : FILTER_LOG )
--User changes
-Add new variations: bubbleT3D, crob, hexaplay3D, hexcrop, hexes, hexnix3D, loonie2, loonie3, nBlur, octapol and synth.
-Allow for pre/post versions of dc_bubble, dc_cylinder and dc_linear whereas before they were omitted.
-When saving a file with multiple embers in it, detect if time values are all the same and if so, start them at zero and increment by 1 for each ember.
-Allow for numerous quality increases to be coalesced into one. It will pick up at the end of the current render.
-Show selection highlight on variations tree in response to mouse hover. This makes it easier to see for which variation or param the current mouse wheel action will apply.
-Make default temporal samples be 100, whereas before it was 1000 which was overkill.
-Require the shift key to be held with delete for deleting an ember to prevent it from triggering when the user enters delete in the edit box.
-This wasn't otherwise fixable without writing a lot more code.
--Bug fixes
-EmberGenome was crashing when generating a sequence from a source file with more than 2 embers in it.
-EmberGenome was improperly handling the first frame of a merge after the last frame of the loop.
-These bugs were due to a previous commit. Revert parts of that commit.
-Prevent a zoom value of less than 0 when reading from xml.
-Slight optimization of the crescents, and mask variations, if the compiler wasn't doing it already.
-Unique file naming was broken because it was looking for _# and the default names ended with -#.
-Disallow renaming of an ember in the library tree to an empty string.
-Severe bug that prevented some variations from being read correctly from params generated outside this program.
-Severe OpenCL randomization bug. The first x coordinates of the first points in the first kernel call of the first ember of a render since the OpenCL renderer object was created were not random and were mostly -1.
-Severe bug when populating xform selection distributions that could sometimes cause a crash due to roundoff error. Fix by using double.
-Limit the max number of variations in a random ember to MAX_CL_VARS, which is 8. This ensures they'll look the same on CPU and GPU.
-Prevent user from saving stylesheet to default.qss, it's a special reserved filename.
--Code changes
-Generalize using the running sum output point inside of a variation for all cases: pre, reg and post.
-Allow for array variables in variations where the address of each element is stored in m_Params.
-Qualify all math functions with std::
-No longer use our own Clamp() in OpenCL, instead use the standard clamp().
-Redesign how functions are used in the variations OpenCL code.
-Add tests to EmberTester to verify some of the new functionality.
-Place more const and override qualifiers on functions where appropriate.
-Add a global rand with a lock to be used very sparingly.
-Use a map instead of a vector for bad param names in Xml parsing.
-Prefix affine interpolation mode defines with "AFFINE_" to make their purpose more clear.
-Allow for variations that change state during iteration by sending a separate copy of the ember to each rendering thread.
-Implement this same functionality with a local struct in OpenCL. It's members are the total of all variables that need to change state within an ember.
-Add Contains() function to Utils.h.
-EmberRender: print names of kernels being printed with --dump_kernel option.
-Clean up EmberTester to handle some of the recent changes.
-Fix various casts.
-Replace % 2 with & 1, even though the compiler was likely doing this already.
-Add new file Variations06.h to accommodate new variations.
-General cleanup.
2015-11-22 17:15:07 -05:00
fullRun = LogScaleDensityFilter ( forceOutput ) ;
2014-10-14 11:53:15 -04:00
}
2014-07-08 03:11:14 -04:00
2014-11-03 02:16:34 -05:00
//Only update state if iterating and filtering finished completely (didn't arrive here via forceOutput).
2015-12-31 19:00:36 -05:00
if ( fullRun = = eRenderStatus : : RENDER_OK & & m_ProcessState = = eProcessState : : ITER_DONE )
m_ProcessState = eProcessState : : FILTER_DONE ;
2014-07-08 03:11:14 -04:00
2014-11-03 02:16:34 -05:00
//Take special action if filtering exited prematurely.
2015-12-31 19:00:36 -05:00
if ( fullRun ! = eRenderStatus : : RENDER_OK )
2014-11-03 02:16:34 -05:00
{
2017-08-28 00:24:33 -04:00
if ( ! ResetBuckets ( false , true ) ) //Reset the accumulator, come back and try again on the next call.
success = eRenderStatus : : RENDER_ERROR ;
else
success = fullRun ;
2014-11-03 02:16:34 -05:00
goto Finish ;
}
2014-07-08 03:11:14 -04:00
2014-11-03 02:16:34 -05:00
if ( m_Abort )
{
2015-12-31 19:00:36 -05:00
success = eRenderStatus : : RENDER_ABORT ;
2014-11-03 02:16:34 -05:00
goto Finish ;
}
2015-12-31 19:00:36 -05:00
2014-11-03 02:16:34 -05:00
//t.Toc("Density estimation filtering time: ", true);
}
2014-07-08 03:11:14 -04:00
2014-10-14 11:53:15 -04:00
AccumOnly :
2015-12-31 19:00:36 -05:00
if ( m_ProcessState = = eProcessState : : FILTER_DONE | | forceOutput )
2014-07-08 03:11:14 -04:00
{
2015-06-28 20:48:26 -04:00
//Original only allowed stages 0 and 1. Add 2 to mean final accum.
//Do not update state/progress on forced output because it will be immediately overwritten.
if ( m_Callback & & ! forceOutput & & ! m_Callback - > ProgressFunc ( m_Ember , m_ProgressParameter , 0 , 2 , 0 ) )
2014-07-08 03:11:14 -04:00
{
2014-10-14 11:53:15 -04:00
Abort ( ) ;
2015-12-31 19:00:36 -05:00
success = eRenderStatus : : RENDER_ABORT ;
2014-10-14 11:53:15 -04:00
goto Finish ;
2014-07-08 03:11:14 -04:00
}
2014-10-14 11:53:15 -04:00
//Make sure a filter has been created.
CreateSpatialFilter ( newFilterAlloc ) ;
2016-03-28 21:49:10 -04:00
m_DensityFilterOffset = m_GutterWidth - size_t ( Clamp < T > ( ( T ( m_SpatialFilter - > FinalFilterWidth ( ) ) - T ( Supersample ( ) ) ) / 2 , 0 , T ( m_GutterWidth ) ) ) ;
2015-03-21 18:27:37 -04:00
m_CurvesSet = m_Ember . m_Curves . CurvesSet ( ) ;
2017-07-22 16:43:35 -04:00
ComputeCurves ( ) ; //Color curves must be re-calculated as well.
2015-03-21 18:27:37 -04:00
2015-12-31 19:00:36 -05:00
if ( AccumulatorToFinalImage ( finalImage , finalOffset ) = = eRenderStatus : : RENDER_OK )
2014-10-14 11:53:15 -04:00
{
m_Stats . m_RenderMs = m_RenderTimer . Toc ( ) ; //Record total time from the very beginning to the very end, including all intermediate calls.
//Even though the ember changes throughought the inner loops because of interpolation, it's probably ok to assign here.
//This will hold the last interpolated value (even though spatial and temporal filters were created based off of one of the first interpolated values).
m_LastEmber = m_Ember ;
2014-07-08 03:11:14 -04:00
2015-12-31 19:00:36 -05:00
if ( m_ProcessState = = eProcessState : : FILTER_DONE ) //Only update state if gotten here legitimately, and not via forceOutput.
2014-07-08 03:11:14 -04:00
{
2015-12-31 19:00:36 -05:00
m_ProcessState = eProcessState : : ACCUM_DONE ;
2014-10-14 11:53:15 -04:00
if ( m_Callback & & ! m_Callback - > ProgressFunc ( m_Ember , m_ProgressParameter , 100.0 , 2 , 0 ) ) //Finished.
2014-07-08 03:11:14 -04:00
{
2014-10-14 11:53:15 -04:00
Abort ( ) ;
2015-12-31 19:00:36 -05:00
success = eRenderStatus : : RENDER_ABORT ;
2014-10-14 11:53:15 -04:00
goto Finish ;
2014-07-08 03:11:14 -04:00
}
}
}
2014-10-14 11:53:15 -04:00
else
{
2015-12-31 19:00:36 -05:00
success = eRenderStatus : : RENDER_ERROR ;
2014-10-14 11:53:15 -04:00
}
}
2015-12-31 19:00:36 -05:00
2014-10-14 11:53:15 -04:00
Finish :
2015-12-31 19:00:36 -05:00
if ( success = = eRenderStatus : : RENDER_OK & & m_Abort ) //If everything ran ok, but they've aborted, record abort as the status.
success = eRenderStatus : : RENDER_ABORT ;
else if ( success ! = eRenderStatus : : RENDER_OK ) //Regardless of abort status, if there was an error, leave that as the return status.
2014-10-14 11:53:15 -04:00
Abort ( ) ;
LeaveRender ( ) ;
m_InRender = false ;
return success ;
2014-07-08 03:11:14 -04:00
}
/// <summary>
2014-10-14 11:53:15 -04:00
/// Return EmberImageComments object with image comments filled out.
/// Run() should have completed before calling this.
2014-07-08 03:11:14 -04:00
/// </summary>
2014-10-14 11:53:15 -04:00
/// <param name="printEditDepth">The depth of the edit tags</param>
/// <param name="hexPalette">If true, embed a hexadecimal palette instead of Xml Color tags, else use Xml color tags.</param>
/// <returns>The EmberImageComments object with image comments filled out</returns>
2014-07-08 03:11:14 -04:00
template < typename T , typename bucketT >
2016-04-03 21:55:12 -04:00
EmberImageComments Renderer < T , bucketT > : : ImageComments ( const EmberStats & stats , size_t printEditDepth , bool hexPalette )
2014-07-08 03:11:14 -04:00
{
2014-10-14 11:53:15 -04:00
ostringstream ss ;
EmberImageComments comments ;
ss . imbue ( std : : locale ( " " ) ) ;
2016-04-03 21:55:12 -04:00
comments . m_Genome = m_EmberToXml . ToString ( m_Ember , " " , printEditDepth , false , hexPalette ) ;
2014-12-07 02:51:44 -05:00
ss < < ( double ( stats . m_Badvals ) / double ( stats . m_Iters ) ) ; //Percentage of bad values to iters.
2014-10-14 11:53:15 -04:00
comments . m_Badvals = ss . str ( ) ; ss . str ( " " ) ;
ss < < stats . m_Iters ;
comments . m_NumIters = ss . str ( ) ; ss . str ( " " ) ; //Total iters.
ss < < ( stats . m_RenderMs / 1000.0 ) ;
comments . m_Runtime = ss . str ( ) ; //Number of seconds for iterating, accumulating and filtering.
return comments ;
2014-07-08 03:11:14 -04:00
}
/// <summary>
2014-10-14 11:53:15 -04:00
/// New virtual functions to be overridden in derived renderers that use the GPU, but not accessed outside.
2014-07-08 03:11:14 -04:00
/// </summary>
/// <summary>
/// Make the final palette used for iteration.
/// </summary>
/// <param name="colorScalar">The color scalar to multiply the ember's palette by</param>
template < typename T , typename bucketT >
void Renderer < T , bucketT > : : MakeDmap ( T colorScalar )
{
--User changes
-Add a palette editor.
-Add support for reading .ugr/.gradient/.gradients palette files.
-Allow toggling on spinners whose minimum value is not zero.
-Allow toggling display of image, affines and grid.
-Add new variations: cylinder2, circlesplit, tile_log, truchet_fill, waves2_radial.
--Bug fixes
-cpow2 was wrong.
-Palettes with rapid changes in color would produce slightly different outputs from Apo/Chaotica. This was due to a long standing bug from flam3.
-Use exec() on Apple and show() on all other OSes for dialog boxes.
-Trying to render a sequence with no frames would crash.
-Selecting multiple xforms and rotating them would produce the wrong rotation.
-Better handling when parsing flames using different encoding, such as unicode and UTF-8.
-Switching between SP/DP didn't reselect the selected flame in the Library tab.
--Code changes
-Make all types concerning palettes be floats, including PaletteTableWidgetItem.
-PaletteTableWidgetItem is no longer templated because all palettes are float.
-Include the source colors for user created gradients.
-Change parallel_for() calls to work with very old versions of TBB which are lingering on some systems.
-Split conditional out of accumulation loop on the CPU for better performance.
-Vectorize summing when doing density filter for better performance.
-Make all usage of palettes be of type float, double is pointless.
-Allow palettes to reside in multiple folders, while ensuring only one of each name is added.
-Refactor some palette path searching code.
-Make ReadFile() throw and catch an exception if the file operation fails.
-A little extra safety in foci and foci3D with a call to Zeps().
-Cast to (real_t) in the OpenCL string for the w variation, which was having trouble compiling on Mac.
-Fixing missing comma between paths in InitPaletteList().
-Move Xml and PaletteList classes into cpp to shorten build times when working on them.
-Remove default param values for IterOpenCLKernelCreator<T>::SharedDataIndexDefines in cpp file.
-Change more NULL to nullptr.
2017-02-26 03:02:21 -05:00
m_Ember . m_Palette . template MakeDmap < bucketT > ( m_Dmap , bucketT ( colorScalar ) ) ;
2014-07-08 03:11:14 -04:00
}
/// <summary>
/// Allocate various buffers if the image dimensions, thread count, or sub batch size
/// has changed.
/// </summary>
/// <returns>True if success, else false</returns>
template < typename T , typename bucketT >
--User changes
-Add support for multiple GPU devices.
--These options are present in the command line and in Fractorium.
-Change scheme of specifying devices from platform,device to just total device index.
--Single number on the command line.
--Change from combo boxes for device selection to a table of all devices in Fractorium.
-Temporal samples defaults to 100 instead of 1000 which was needless overkill.
--Bug fixes
-EmberAnimate, EmberRender, FractoriumSettings, FinalRenderDialog: Fix wrong order of arguments to Clamp() when assigning thread priority.
-VariationsDC.h: Fix NVidia OpenCL compilation error in DCTriangleVariation.
-FractoriumXformsColor.cpp: Checking for null pixmap pointer is not enough, must also check if the underlying buffer is null via call to QPixmap::isNull().
--Code changes
-Ember.h: Add case for FLAME_MOTION_NONE and default in ApplyFlameMotion().
-EmberMotion.h: Call base constructor.
-EmberPch.h: #pragma once only on Windows.
-EmberToXml.h:
--Handle different types of exceptions.
--Add default cases to ToString().
-Isaac.h: Remove unused variable in constructor.
-Point.h: Call base constructor in Color().
-Renderer.h/cpp:
--Add bool to Alloc() to only allocate memory for the histogram. Needed for multi-GPU.
--Make CoordMap() return a const ref, not a pointer.
-SheepTools.h:
--Use 64-bit types like the rest of the code already does.
--Fix some comment misspellings.
-Timing.h: Make BeginTime(), EndTime(), ElapsedTime() and Format() be const functions.
-Utils.h:
--Add new functions Equal() and Split().
--Handle more exception types in ReadFile().
--Get rid of most legacy blending of C and C++ argument parsing.
-XmlToEmber.h:
--Get rid of most legacy blending of C and C++ code from flam3.
--Remove some unused variables.
-EmberAnimate:
--Support multi-GPU processing that alternates full frames between devices.
--Use OpenCLInfo instead of OpenCLWrapper for --openclinfo option.
--Remove bucketT template parameter, and hard code float in its place.
--If a render fails, exit since there is no point in continuing an animation with a missing frame.
--Pass variables to threaded save better, which most likely fixes a very subtle bug that existed before.
--Remove some unused variables.
-EmberGenome, EmberRender:
--Support multi-GPU processing that alternates full frames between devices.
--Use OpenCLInfo instead of OpenCLWrapper for --openclinfo option.
--Remove bucketT template parameter, and hard code float in its place.
-EmberRender:
--Support multi-GPU processing that alternates full frames between devices.
--Use OpenCLInfo instead of OpenCLWrapper for --openclinfo option.
--Remove bucketT template parameter, and hard code float in its place.
--Only print values when not rendering with OpenCL, since they're always 0 in that case.
-EmberCLPch.h:
--#pragma once only on Windows.
--#include <atomic>.
-IterOpenCLKernelCreator.h: Add new kernel for summing two histograms. This is needed for multi-GPU.
-OpenCLWrapper.h:
--Move all OpenCL info related code into its own class OpenCLInfo.
--Add members to cache the values of global memory size and max allocation size.
-RendererCL.h/cpp:
--Redesign to accomodate multi-GPU.
--Constructor now takes a vector of devices.
--Remove DumpErrorReport() function, it's handled in the base.
--ClearBuffer(), ReadPoints(), WritePoints(), ReadHist() and WriteHist() now optionally take a device index as a parameter.
--MakeDmap() override and m_DmapCL member removed because it no longer applies since the histogram is always float since the last commit.
--Add new function SumDeviceHist() to sum histograms from two devices by first copying to a temporary on the host, then a temporary on the device, then summing.
--m_Calls member removed, as it's now per-device.
--OpenCLWrapper removed.
--m_Seeds member is now a vector of vector of seeds, to accomodate a separate and different array of seeds for each device.
--Added member m_Devices, a vector of unique_ptr of RendererCLDevice.
-EmberCommon.h
--Added Devices() function to convert from a vector of device indices to a vector of platform,device indices.
--Changed CreateRenderer() to accept a vector of devices to create a single RendererCL which will split work across multiple devices.
--Added CreateRenderers() function to accept a vector of devices to create multiple RendererCL, each which will render on a single device.
--Add more comments to some existing functions.
-EmberCommonPch.h: #pragma once only on Windows.
-EmberOptions.h:
--Remove --platform option, it's just sequential device number now with the --device option.
--Make --out be OPT_USE_RENDER instead of OPT_RENDER_ANIM since it's an error condition when animating. It makes no sense to write all frames to a single image.
--Add Devices() function to parse comma separated --device option string and return a vector of device indices.
--Make int and uint types be 64-bit, so intmax_t and size_t.
--Make better use of macros.
-JpegUtils.h: Make string parameters to WriteJpeg() and WritePng() be const ref.
-All project files: Turn off buffer security check option in Visual Studio (/Gs-)
-deployment.pri: Remove the line OTHER_FILES +=, it's pointless and was causing problems.
-Ember.pro, EmberCL.pro: Add CONFIG += plugin, otherwise it wouldn't link.
-EmberCL.pro: Add new files for multi-GPU support.
-build_all.sh: use -j4 and QMAKE=${QMAKE:/usr/bin/qmake}
-shared_settings.pri:
-Add version string.
-Remove old DESTDIR definitions.
-Add the following lines or else nothing would build:
CONFIG(release, debug|release) {
CONFIG += warn_off
DESTDIR = ../../../Bin/release
}
CONFIG(debug, debug|release) {
DESTDIR = ../../../Bin/debug
}
QMAKE_POST_LINK += $$quote(cp --update ../../../Data/flam3-palettes.xml $${DESTDIR}$$escape_expand(\n\t))
LIBS += -L/usr/lib -lpthread
-AboutDialog.ui: Another futile attempt to make it look correct on Linux.
-FinalRenderDialog.h/cpp:
--Add support for multi-GPU.
--Change from combo boxes for device selection to a table of all devices.
--Ensure device selection makes sense.
--Remove "FinalRender" prefix of various function names, it's implied given the context.
-FinalRenderEmberController.h/cpp:
--Add support for multi-GPU.
--Change m_FinishedImageCount to be atomic.
--Move CancelRender() from the base to FinalRenderEmberController<T>.
--Refactor RenderComplete() to omit any progress related functionality or image saving since it can be potentially ran in a thread.
--Consolidate setting various renderer fields into SyncGuiToRenderer().
-Fractorium.cpp: Allow for resizing of the options dialog to show the entire device table.
-FractoriumCommon.h: Add various functions to handle a table showing the available OpenCL devices on the system.
-FractoriumEmberController.h/cpp: Remove m_FinalImageIndex, it's no longer needed.
-FractoriumRender.cpp: Scale the interactive sub batch count and quality by the number of devices used.
-FractoriumSettings.h/cpp:
--Temporal samples defaults to 100 instead of 1000 which was needless overkill.
--Add multi-GPU support, remove old device,platform pair.
-FractoriumToolbar.cpp: Disable OpenCL toolbar button if there are no devices present on the system.
-FractoriumOptionsDialog.h/cpp:
--Add support for multi-GPU.
--Consolidate more assignments in DataToGui().
--Enable/disable CPU/OpenCL items in response to OpenCL checkbox event.
-Misc: Convert almost everything to size_t for unsigned, intmax_t for signed.
2015-09-12 21:33:45 -04:00
bool Renderer < T , bucketT > : : Alloc ( bool histOnly )
2014-07-08 03:11:14 -04:00
{
bool b = true ;
bool lock =
( m_SuperSize ! = m_HistBuckets . size ( ) ) | |
( m_SuperSize ! = m_AccumulatorBuckets . size ( ) ) | |
( m_ThreadsToUse ! = m_Samples . size ( ) ) | |
2014-11-28 04:37:51 -05:00
( m_Samples [ 0 ] . size ( ) ! = SubBatchSize ( ) ) ;
2014-07-08 03:11:14 -04:00
if ( lock )
EnterResize ( ) ;
if ( m_SuperSize ! = m_HistBuckets . size ( ) )
{
m_HistBuckets . resize ( m_SuperSize ) ;
if ( m_ReclaimOnResize )
m_HistBuckets . shrink_to_fit ( ) ;
b & = ( m_HistBuckets . size ( ) = = m_SuperSize ) ;
}
--User changes
-Add support for multiple GPU devices.
--These options are present in the command line and in Fractorium.
-Change scheme of specifying devices from platform,device to just total device index.
--Single number on the command line.
--Change from combo boxes for device selection to a table of all devices in Fractorium.
-Temporal samples defaults to 100 instead of 1000 which was needless overkill.
--Bug fixes
-EmberAnimate, EmberRender, FractoriumSettings, FinalRenderDialog: Fix wrong order of arguments to Clamp() when assigning thread priority.
-VariationsDC.h: Fix NVidia OpenCL compilation error in DCTriangleVariation.
-FractoriumXformsColor.cpp: Checking for null pixmap pointer is not enough, must also check if the underlying buffer is null via call to QPixmap::isNull().
--Code changes
-Ember.h: Add case for FLAME_MOTION_NONE and default in ApplyFlameMotion().
-EmberMotion.h: Call base constructor.
-EmberPch.h: #pragma once only on Windows.
-EmberToXml.h:
--Handle different types of exceptions.
--Add default cases to ToString().
-Isaac.h: Remove unused variable in constructor.
-Point.h: Call base constructor in Color().
-Renderer.h/cpp:
--Add bool to Alloc() to only allocate memory for the histogram. Needed for multi-GPU.
--Make CoordMap() return a const ref, not a pointer.
-SheepTools.h:
--Use 64-bit types like the rest of the code already does.
--Fix some comment misspellings.
-Timing.h: Make BeginTime(), EndTime(), ElapsedTime() and Format() be const functions.
-Utils.h:
--Add new functions Equal() and Split().
--Handle more exception types in ReadFile().
--Get rid of most legacy blending of C and C++ argument parsing.
-XmlToEmber.h:
--Get rid of most legacy blending of C and C++ code from flam3.
--Remove some unused variables.
-EmberAnimate:
--Support multi-GPU processing that alternates full frames between devices.
--Use OpenCLInfo instead of OpenCLWrapper for --openclinfo option.
--Remove bucketT template parameter, and hard code float in its place.
--If a render fails, exit since there is no point in continuing an animation with a missing frame.
--Pass variables to threaded save better, which most likely fixes a very subtle bug that existed before.
--Remove some unused variables.
-EmberGenome, EmberRender:
--Support multi-GPU processing that alternates full frames between devices.
--Use OpenCLInfo instead of OpenCLWrapper for --openclinfo option.
--Remove bucketT template parameter, and hard code float in its place.
-EmberRender:
--Support multi-GPU processing that alternates full frames between devices.
--Use OpenCLInfo instead of OpenCLWrapper for --openclinfo option.
--Remove bucketT template parameter, and hard code float in its place.
--Only print values when not rendering with OpenCL, since they're always 0 in that case.
-EmberCLPch.h:
--#pragma once only on Windows.
--#include <atomic>.
-IterOpenCLKernelCreator.h: Add new kernel for summing two histograms. This is needed for multi-GPU.
-OpenCLWrapper.h:
--Move all OpenCL info related code into its own class OpenCLInfo.
--Add members to cache the values of global memory size and max allocation size.
-RendererCL.h/cpp:
--Redesign to accomodate multi-GPU.
--Constructor now takes a vector of devices.
--Remove DumpErrorReport() function, it's handled in the base.
--ClearBuffer(), ReadPoints(), WritePoints(), ReadHist() and WriteHist() now optionally take a device index as a parameter.
--MakeDmap() override and m_DmapCL member removed because it no longer applies since the histogram is always float since the last commit.
--Add new function SumDeviceHist() to sum histograms from two devices by first copying to a temporary on the host, then a temporary on the device, then summing.
--m_Calls member removed, as it's now per-device.
--OpenCLWrapper removed.
--m_Seeds member is now a vector of vector of seeds, to accomodate a separate and different array of seeds for each device.
--Added member m_Devices, a vector of unique_ptr of RendererCLDevice.
-EmberCommon.h
--Added Devices() function to convert from a vector of device indices to a vector of platform,device indices.
--Changed CreateRenderer() to accept a vector of devices to create a single RendererCL which will split work across multiple devices.
--Added CreateRenderers() function to accept a vector of devices to create multiple RendererCL, each which will render on a single device.
--Add more comments to some existing functions.
-EmberCommonPch.h: #pragma once only on Windows.
-EmberOptions.h:
--Remove --platform option, it's just sequential device number now with the --device option.
--Make --out be OPT_USE_RENDER instead of OPT_RENDER_ANIM since it's an error condition when animating. It makes no sense to write all frames to a single image.
--Add Devices() function to parse comma separated --device option string and return a vector of device indices.
--Make int and uint types be 64-bit, so intmax_t and size_t.
--Make better use of macros.
-JpegUtils.h: Make string parameters to WriteJpeg() and WritePng() be const ref.
-All project files: Turn off buffer security check option in Visual Studio (/Gs-)
-deployment.pri: Remove the line OTHER_FILES +=, it's pointless and was causing problems.
-Ember.pro, EmberCL.pro: Add CONFIG += plugin, otherwise it wouldn't link.
-EmberCL.pro: Add new files for multi-GPU support.
-build_all.sh: use -j4 and QMAKE=${QMAKE:/usr/bin/qmake}
-shared_settings.pri:
-Add version string.
-Remove old DESTDIR definitions.
-Add the following lines or else nothing would build:
CONFIG(release, debug|release) {
CONFIG += warn_off
DESTDIR = ../../../Bin/release
}
CONFIG(debug, debug|release) {
DESTDIR = ../../../Bin/debug
}
QMAKE_POST_LINK += $$quote(cp --update ../../../Data/flam3-palettes.xml $${DESTDIR}$$escape_expand(\n\t))
LIBS += -L/usr/lib -lpthread
-AboutDialog.ui: Another futile attempt to make it look correct on Linux.
-FinalRenderDialog.h/cpp:
--Add support for multi-GPU.
--Change from combo boxes for device selection to a table of all devices.
--Ensure device selection makes sense.
--Remove "FinalRender" prefix of various function names, it's implied given the context.
-FinalRenderEmberController.h/cpp:
--Add support for multi-GPU.
--Change m_FinishedImageCount to be atomic.
--Move CancelRender() from the base to FinalRenderEmberController<T>.
--Refactor RenderComplete() to omit any progress related functionality or image saving since it can be potentially ran in a thread.
--Consolidate setting various renderer fields into SyncGuiToRenderer().
-Fractorium.cpp: Allow for resizing of the options dialog to show the entire device table.
-FractoriumCommon.h: Add various functions to handle a table showing the available OpenCL devices on the system.
-FractoriumEmberController.h/cpp: Remove m_FinalImageIndex, it's no longer needed.
-FractoriumRender.cpp: Scale the interactive sub batch count and quality by the number of devices used.
-FractoriumSettings.h/cpp:
--Temporal samples defaults to 100 instead of 1000 which was needless overkill.
--Add multi-GPU support, remove old device,platform pair.
-FractoriumToolbar.cpp: Disable OpenCL toolbar button if there are no devices present on the system.
-FractoriumOptionsDialog.h/cpp:
--Add support for multi-GPU.
--Consolidate more assignments in DataToGui().
--Enable/disable CPU/OpenCL items in response to OpenCL checkbox event.
-Misc: Convert almost everything to size_t for unsigned, intmax_t for signed.
2015-09-12 21:33:45 -04:00
if ( histOnly )
{
if ( lock )
LeaveResize ( ) ;
return b ;
}
2014-07-08 03:11:14 -04:00
if ( m_SuperSize ! = m_AccumulatorBuckets . size ( ) )
{
m_AccumulatorBuckets . resize ( m_SuperSize ) ;
if ( m_ReclaimOnResize )
m_AccumulatorBuckets . shrink_to_fit ( ) ;
b & = ( m_AccumulatorBuckets . size ( ) = = m_SuperSize ) ;
}
if ( m_ThreadsToUse ! = m_Samples . size ( ) )
{
m_Samples . resize ( m_ThreadsToUse ) ;
if ( m_ReclaimOnResize )
m_Samples . shrink_to_fit ( ) ;
b & = ( m_Samples . size ( ) = = m_ThreadsToUse ) ;
}
2015-05-03 20:13:14 -04:00
for ( auto & sample : m_Samples )
2014-07-08 03:11:14 -04:00
{
2015-05-03 20:13:14 -04:00
if ( sample . size ( ) ! = SubBatchSize ( ) )
2014-07-08 03:11:14 -04:00
{
2015-05-03 20:13:14 -04:00
sample . resize ( SubBatchSize ( ) ) ;
2014-07-08 03:11:14 -04:00
if ( m_ReclaimOnResize )
2015-05-03 20:13:14 -04:00
sample . shrink_to_fit ( ) ;
2014-07-08 03:11:14 -04:00
2015-05-03 20:13:14 -04:00
b & = ( sample . size ( ) = = SubBatchSize ( ) ) ;
2014-07-08 03:11:14 -04:00
}
}
--User changes
-Support 4k monitors, and in general, properly scale any monitor that is not HD.
-Allow for a spatial filter of radius zero, which means do not use a spatial filter.
-Add new variations: concentric, cpow3, helicoid, helix, rand_cubes, sphereblur.
-Use a new method for computing elliptic which is more precise. Developed by Discord user Claude.
-Remove the 8 variation per xform limitation on the GPU.
-Allow for loading the last flame file on startup, rather than randoms.
-Use two different default quality values in the interactive renderer, one each for CPU and GPU.
-Creating linked xforms was using non-standard behavior. Make it match Apo and also support creating multiple linked xforms at once.
--Bug fixes
-No variations in an xform used to have the same behavior as a single linear variation with weight 1. While sensible, this breaks backward compatibility. No variations now sets the output point to zeroes.
-Prevent crashing the program when adjusting a value on the main window while a final render is in progress.
-The xaos table was inverted.
--Code changes
-Convert projects to Visual Studio 2017.
-Change bad vals from +- 1e10 to +-1e20.
-Reintroduce the symmetry tag in xforms for legacy support in programs that do not use color_speed.
-Compiler will not let us use default values in templated member functions anymore.
2017-11-26 20:27:00 -05:00
if ( ! m_StandardIterator . get ( ) )
m_StandardIterator = make_unique < StandardIterator < T > > ( ) ;
if ( ! m_XaosIterator . get ( ) )
m_XaosIterator = make_unique < XaosIterator < T > > ( ) ;
2014-07-08 03:11:14 -04:00
if ( lock )
LeaveResize ( ) ;
return b ;
}
/// <summary>
/// Clear histogram and/or density filtering buffers to all zeroes.
/// </summary>
/// <param name="resetHist">Clear histogram if true, else don't.</param>
/// <param name="resetAccum">Clear density filtering buffer if true, else don't.</param>
/// <returns>True if anything was cleared, else false.</returns>
template < typename T , typename bucketT >
bool Renderer < T , bucketT > : : ResetBuckets ( bool resetHist , bool resetAccum )
{
//parallel_invoke(
//[&]
//{
2014-10-14 11:53:15 -04:00
if ( resetHist & & ! m_HistBuckets . empty ( ) )
Memset ( m_HistBuckets ) ;
2015-12-31 19:00:36 -05:00
2014-07-08 03:11:14 -04:00
//},
//[&]
//{
2014-10-14 11:53:15 -04:00
if ( resetAccum & & ! m_AccumulatorBuckets . empty ( ) )
Memset ( m_AccumulatorBuckets ) ;
2014-07-08 03:11:14 -04:00
2015-12-31 19:00:36 -05:00
//});
2014-07-08 03:11:14 -04:00
return resetHist | | resetAccum ;
}
--User changes
-Add new variations: bubbleT3D, crob, hexaplay3D, hexcrop, hexes, hexnix3D, loonie2, loonie3, nBlur, octapol and synth.
-Allow for pre/post versions of dc_bubble, dc_cylinder and dc_linear whereas before they were omitted.
-When saving a file with multiple embers in it, detect if time values are all the same and if so, start them at zero and increment by 1 for each ember.
-Allow for numerous quality increases to be coalesced into one. It will pick up at the end of the current render.
-Show selection highlight on variations tree in response to mouse hover. This makes it easier to see for which variation or param the current mouse wheel action will apply.
-Make default temporal samples be 100, whereas before it was 1000 which was overkill.
-Require the shift key to be held with delete for deleting an ember to prevent it from triggering when the user enters delete in the edit box.
-This wasn't otherwise fixable without writing a lot more code.
--Bug fixes
-EmberGenome was crashing when generating a sequence from a source file with more than 2 embers in it.
-EmberGenome was improperly handling the first frame of a merge after the last frame of the loop.
-These bugs were due to a previous commit. Revert parts of that commit.
-Prevent a zoom value of less than 0 when reading from xml.
-Slight optimization of the crescents, and mask variations, if the compiler wasn't doing it already.
-Unique file naming was broken because it was looking for _# and the default names ended with -#.
-Disallow renaming of an ember in the library tree to an empty string.
-Severe bug that prevented some variations from being read correctly from params generated outside this program.
-Severe OpenCL randomization bug. The first x coordinates of the first points in the first kernel call of the first ember of a render since the OpenCL renderer object was created were not random and were mostly -1.
-Severe bug when populating xform selection distributions that could sometimes cause a crash due to roundoff error. Fix by using double.
-Limit the max number of variations in a random ember to MAX_CL_VARS, which is 8. This ensures they'll look the same on CPU and GPU.
-Prevent user from saving stylesheet to default.qss, it's a special reserved filename.
--Code changes
-Generalize using the running sum output point inside of a variation for all cases: pre, reg and post.
-Allow for array variables in variations where the address of each element is stored in m_Params.
-Qualify all math functions with std::
-No longer use our own Clamp() in OpenCL, instead use the standard clamp().
-Redesign how functions are used in the variations OpenCL code.
-Add tests to EmberTester to verify some of the new functionality.
-Place more const and override qualifiers on functions where appropriate.
-Add a global rand with a lock to be used very sparingly.
-Use a map instead of a vector for bad param names in Xml parsing.
-Prefix affine interpolation mode defines with "AFFINE_" to make their purpose more clear.
-Allow for variations that change state during iteration by sending a separate copy of the ember to each rendering thread.
-Implement this same functionality with a local struct in OpenCL. It's members are the total of all variables that need to change state within an ember.
-Add Contains() function to Utils.h.
-EmberRender: print names of kernels being printed with --dump_kernel option.
-Clean up EmberTester to handle some of the recent changes.
-Fix various casts.
-Replace % 2 with & 1, even though the compiler was likely doing this already.
-Add new file Variations06.h to accommodate new variations.
-General cleanup.
2015-11-22 17:15:07 -05:00
/// <summary>
2017-07-22 16:43:35 -04:00
/// THIS IS UNUSED.
--User changes
-Add new variations: bubbleT3D, crob, hexaplay3D, hexcrop, hexes, hexnix3D, loonie2, loonie3, nBlur, octapol and synth.
-Allow for pre/post versions of dc_bubble, dc_cylinder and dc_linear whereas before they were omitted.
-When saving a file with multiple embers in it, detect if time values are all the same and if so, start them at zero and increment by 1 for each ember.
-Allow for numerous quality increases to be coalesced into one. It will pick up at the end of the current render.
-Show selection highlight on variations tree in response to mouse hover. This makes it easier to see for which variation or param the current mouse wheel action will apply.
-Make default temporal samples be 100, whereas before it was 1000 which was overkill.
-Require the shift key to be held with delete for deleting an ember to prevent it from triggering when the user enters delete in the edit box.
-This wasn't otherwise fixable without writing a lot more code.
--Bug fixes
-EmberGenome was crashing when generating a sequence from a source file with more than 2 embers in it.
-EmberGenome was improperly handling the first frame of a merge after the last frame of the loop.
-These bugs were due to a previous commit. Revert parts of that commit.
-Prevent a zoom value of less than 0 when reading from xml.
-Slight optimization of the crescents, and mask variations, if the compiler wasn't doing it already.
-Unique file naming was broken because it was looking for _# and the default names ended with -#.
-Disallow renaming of an ember in the library tree to an empty string.
-Severe bug that prevented some variations from being read correctly from params generated outside this program.
-Severe OpenCL randomization bug. The first x coordinates of the first points in the first kernel call of the first ember of a render since the OpenCL renderer object was created were not random and were mostly -1.
-Severe bug when populating xform selection distributions that could sometimes cause a crash due to roundoff error. Fix by using double.
-Limit the max number of variations in a random ember to MAX_CL_VARS, which is 8. This ensures they'll look the same on CPU and GPU.
-Prevent user from saving stylesheet to default.qss, it's a special reserved filename.
--Code changes
-Generalize using the running sum output point inside of a variation for all cases: pre, reg and post.
-Allow for array variables in variations where the address of each element is stored in m_Params.
-Qualify all math functions with std::
-No longer use our own Clamp() in OpenCL, instead use the standard clamp().
-Redesign how functions are used in the variations OpenCL code.
-Add tests to EmberTester to verify some of the new functionality.
-Place more const and override qualifiers on functions where appropriate.
-Add a global rand with a lock to be used very sparingly.
-Use a map instead of a vector for bad param names in Xml parsing.
-Prefix affine interpolation mode defines with "AFFINE_" to make their purpose more clear.
-Allow for variations that change state during iteration by sending a separate copy of the ember to each rendering thread.
-Implement this same functionality with a local struct in OpenCL. It's members are the total of all variables that need to change state within an ember.
-Add Contains() function to Utils.h.
-EmberRender: print names of kernels being printed with --dump_kernel option.
-Clean up EmberTester to handle some of the recent changes.
-Fix various casts.
-Replace % 2 with & 1, even though the compiler was likely doing this already.
-Add new file Variations06.h to accommodate new variations.
-General cleanup.
2015-11-22 17:15:07 -05:00
/// Log scales a single row with a specially structured loop that will be vectorized by the compiler.
/// Note this adds an epsilon to the denomiator used to compute the logScale
/// value because the conditional check for zero would have prevented the loop from
/// being vectorized.
/// </summary>
/// <param name="row">The absolute element index in the histogram this row starts on</param>
/// <param name="rowEnd">The absolute element index in the histogram this row ends on</param>
template < typename T , typename bucketT >
void Renderer < T , bucketT > : : VectorizedLogScale ( size_t row , size_t rowEnd )
{
float k1 = float ( m_K1 ) ; //All types must be float.
float k2 = float ( m_K2 ) ;
auto * __restrict hist = m_HistBuckets . data ( ) ; //Vectorizer can't tell these point to different locations.
auto * __restrict acc = m_AccumulatorBuckets . data ( ) ;
for ( size_t i = row ; i < rowEnd ; i + + )
{
float logScale = ( k1 * std : : log ( 1.0f + hist [ i ] . a * k2 ) ) / ( hist [ i ] . a + std : : numeric_limits < float > : : epsilon ( ) ) ;
acc [ i ] . r = hist [ i ] . r * logScale ; //Must break these out individually. Vectorizer can't reason about vec4's overloaded * operator.
acc [ i ] . g = hist [ i ] . g * logScale ;
acc [ i ] . b = hist [ i ] . b * logScale ;
acc [ i ] . a = hist [ i ] . a * logScale ;
}
}
2014-07-08 03:11:14 -04:00
/// <summary>
/// Perform log scale density filtering.
/// Base case for simple log scale density estimation as discussed (mostly) in the paper
/// in section 4, p. 6-9.
/// </summary>
--User changes
-Add new variations: bubbleT3D, crob, hexaplay3D, hexcrop, hexes, hexnix3D, loonie2, loonie3, nBlur, octapol and synth.
-Allow for pre/post versions of dc_bubble, dc_cylinder and dc_linear whereas before they were omitted.
-When saving a file with multiple embers in it, detect if time values are all the same and if so, start them at zero and increment by 1 for each ember.
-Allow for numerous quality increases to be coalesced into one. It will pick up at the end of the current render.
-Show selection highlight on variations tree in response to mouse hover. This makes it easier to see for which variation or param the current mouse wheel action will apply.
-Make default temporal samples be 100, whereas before it was 1000 which was overkill.
-Require the shift key to be held with delete for deleting an ember to prevent it from triggering when the user enters delete in the edit box.
-This wasn't otherwise fixable without writing a lot more code.
--Bug fixes
-EmberGenome was crashing when generating a sequence from a source file with more than 2 embers in it.
-EmberGenome was improperly handling the first frame of a merge after the last frame of the loop.
-These bugs were due to a previous commit. Revert parts of that commit.
-Prevent a zoom value of less than 0 when reading from xml.
-Slight optimization of the crescents, and mask variations, if the compiler wasn't doing it already.
-Unique file naming was broken because it was looking for _# and the default names ended with -#.
-Disallow renaming of an ember in the library tree to an empty string.
-Severe bug that prevented some variations from being read correctly from params generated outside this program.
-Severe OpenCL randomization bug. The first x coordinates of the first points in the first kernel call of the first ember of a render since the OpenCL renderer object was created were not random and were mostly -1.
-Severe bug when populating xform selection distributions that could sometimes cause a crash due to roundoff error. Fix by using double.
-Limit the max number of variations in a random ember to MAX_CL_VARS, which is 8. This ensures they'll look the same on CPU and GPU.
-Prevent user from saving stylesheet to default.qss, it's a special reserved filename.
--Code changes
-Generalize using the running sum output point inside of a variation for all cases: pre, reg and post.
-Allow for array variables in variations where the address of each element is stored in m_Params.
-Qualify all math functions with std::
-No longer use our own Clamp() in OpenCL, instead use the standard clamp().
-Redesign how functions are used in the variations OpenCL code.
-Add tests to EmberTester to verify some of the new functionality.
-Place more const and override qualifiers on functions where appropriate.
-Add a global rand with a lock to be used very sparingly.
-Use a map instead of a vector for bad param names in Xml parsing.
-Prefix affine interpolation mode defines with "AFFINE_" to make their purpose more clear.
-Allow for variations that change state during iteration by sending a separate copy of the ember to each rendering thread.
-Implement this same functionality with a local struct in OpenCL. It's members are the total of all variables that need to change state within an ember.
-Add Contains() function to Utils.h.
-EmberRender: print names of kernels being printed with --dump_kernel option.
-Clean up EmberTester to handle some of the recent changes.
-Fix various casts.
-Replace % 2 with & 1, even though the compiler was likely doing this already.
-Add new file Variations06.h to accommodate new variations.
-General cleanup.
2015-11-22 17:15:07 -05:00
/// <param name="forceOutput">Whether this output was forced due to an interactive render</param>
2014-07-08 03:11:14 -04:00
/// <returns>True if not prematurely aborted, else false.</returns>
template < typename T , typename bucketT >
--User changes
-Add new variations: bubbleT3D, crob, hexaplay3D, hexcrop, hexes, hexnix3D, loonie2, loonie3, nBlur, octapol and synth.
-Allow for pre/post versions of dc_bubble, dc_cylinder and dc_linear whereas before they were omitted.
-When saving a file with multiple embers in it, detect if time values are all the same and if so, start them at zero and increment by 1 for each ember.
-Allow for numerous quality increases to be coalesced into one. It will pick up at the end of the current render.
-Show selection highlight on variations tree in response to mouse hover. This makes it easier to see for which variation or param the current mouse wheel action will apply.
-Make default temporal samples be 100, whereas before it was 1000 which was overkill.
-Require the shift key to be held with delete for deleting an ember to prevent it from triggering when the user enters delete in the edit box.
-This wasn't otherwise fixable without writing a lot more code.
--Bug fixes
-EmberGenome was crashing when generating a sequence from a source file with more than 2 embers in it.
-EmberGenome was improperly handling the first frame of a merge after the last frame of the loop.
-These bugs were due to a previous commit. Revert parts of that commit.
-Prevent a zoom value of less than 0 when reading from xml.
-Slight optimization of the crescents, and mask variations, if the compiler wasn't doing it already.
-Unique file naming was broken because it was looking for _# and the default names ended with -#.
-Disallow renaming of an ember in the library tree to an empty string.
-Severe bug that prevented some variations from being read correctly from params generated outside this program.
-Severe OpenCL randomization bug. The first x coordinates of the first points in the first kernel call of the first ember of a render since the OpenCL renderer object was created were not random and were mostly -1.
-Severe bug when populating xform selection distributions that could sometimes cause a crash due to roundoff error. Fix by using double.
-Limit the max number of variations in a random ember to MAX_CL_VARS, which is 8. This ensures they'll look the same on CPU and GPU.
-Prevent user from saving stylesheet to default.qss, it's a special reserved filename.
--Code changes
-Generalize using the running sum output point inside of a variation for all cases: pre, reg and post.
-Allow for array variables in variations where the address of each element is stored in m_Params.
-Qualify all math functions with std::
-No longer use our own Clamp() in OpenCL, instead use the standard clamp().
-Redesign how functions are used in the variations OpenCL code.
-Add tests to EmberTester to verify some of the new functionality.
-Place more const and override qualifiers on functions where appropriate.
-Add a global rand with a lock to be used very sparingly.
-Use a map instead of a vector for bad param names in Xml parsing.
-Prefix affine interpolation mode defines with "AFFINE_" to make their purpose more clear.
-Allow for variations that change state during iteration by sending a separate copy of the ember to each rendering thread.
-Implement this same functionality with a local struct in OpenCL. It's members are the total of all variables that need to change state within an ember.
-Add Contains() function to Utils.h.
-EmberRender: print names of kernels being printed with --dump_kernel option.
-Clean up EmberTester to handle some of the recent changes.
-Fix various casts.
-Replace % 2 with & 1, even though the compiler was likely doing this already.
-Add new file Variations06.h to accommodate new variations.
-General cleanup.
2015-11-22 17:15:07 -05:00
eRenderStatus Renderer < T , bucketT > : : LogScaleDensityFilter ( bool forceOutput )
2014-07-08 03:11:14 -04:00
{
2014-10-14 11:53:15 -04:00
size_t startRow = 0 ;
size_t endRow = m_SuperRasH ;
size_t endCol = m_SuperRasW ;
2014-07-08 03:11:14 -04:00
//Timing t(4);
--User changes
-Add a palette editor.
-Add support for reading .ugr/.gradient/.gradients palette files.
-Allow toggling on spinners whose minimum value is not zero.
-Allow toggling display of image, affines and grid.
-Add new variations: cylinder2, circlesplit, tile_log, truchet_fill, waves2_radial.
--Bug fixes
-cpow2 was wrong.
-Palettes with rapid changes in color would produce slightly different outputs from Apo/Chaotica. This was due to a long standing bug from flam3.
-Use exec() on Apple and show() on all other OSes for dialog boxes.
-Trying to render a sequence with no frames would crash.
-Selecting multiple xforms and rotating them would produce the wrong rotation.
-Better handling when parsing flames using different encoding, such as unicode and UTF-8.
-Switching between SP/DP didn't reselect the selected flame in the Library tab.
--Code changes
-Make all types concerning palettes be floats, including PaletteTableWidgetItem.
-PaletteTableWidgetItem is no longer templated because all palettes are float.
-Include the source colors for user created gradients.
-Change parallel_for() calls to work with very old versions of TBB which are lingering on some systems.
-Split conditional out of accumulation loop on the CPU for better performance.
-Vectorize summing when doing density filter for better performance.
-Make all usage of palettes be of type float, double is pointless.
-Allow palettes to reside in multiple folders, while ensuring only one of each name is added.
-Refactor some palette path searching code.
-Make ReadFile() throw and catch an exception if the file operation fails.
-A little extra safety in foci and foci3D with a call to Zeps().
-Cast to (real_t) in the OpenCL string for the w variation, which was having trouble compiling on Mac.
-Fixing missing comma between paths in InitPaletteList().
-Move Xml and PaletteList classes into cpp to shorten build times when working on them.
-Remove default param values for IterOpenCLKernelCreator<T>::SharedDataIndexDefines in cpp file.
-Change more NULL to nullptr.
2017-02-26 03:02:21 -05:00
//Original didn't parallelize this, doing so gives a 50-75% speedup.
//The value can be directly assigned, which is quicker than summing.
parallel_for ( startRow , endRow , size_t ( 1 ) , [ & ] ( size_t j )
2014-07-08 03:11:14 -04:00
{
--User changes
-Add a palette editor.
-Add support for reading .ugr/.gradient/.gradients palette files.
-Allow toggling on spinners whose minimum value is not zero.
-Allow toggling display of image, affines and grid.
-Add new variations: cylinder2, circlesplit, tile_log, truchet_fill, waves2_radial.
--Bug fixes
-cpow2 was wrong.
-Palettes with rapid changes in color would produce slightly different outputs from Apo/Chaotica. This was due to a long standing bug from flam3.
-Use exec() on Apple and show() on all other OSes for dialog boxes.
-Trying to render a sequence with no frames would crash.
-Selecting multiple xforms and rotating them would produce the wrong rotation.
-Better handling when parsing flames using different encoding, such as unicode and UTF-8.
-Switching between SP/DP didn't reselect the selected flame in the Library tab.
--Code changes
-Make all types concerning palettes be floats, including PaletteTableWidgetItem.
-PaletteTableWidgetItem is no longer templated because all palettes are float.
-Include the source colors for user created gradients.
-Change parallel_for() calls to work with very old versions of TBB which are lingering on some systems.
-Split conditional out of accumulation loop on the CPU for better performance.
-Vectorize summing when doing density filter for better performance.
-Make all usage of palettes be of type float, double is pointless.
-Allow palettes to reside in multiple folders, while ensuring only one of each name is added.
-Refactor some palette path searching code.
-Make ReadFile() throw and catch an exception if the file operation fails.
-A little extra safety in foci and foci3D with a call to Zeps().
-Cast to (real_t) in the OpenCL string for the w variation, which was having trouble compiling on Mac.
-Fixing missing comma between paths in InitPaletteList().
-Move Xml and PaletteList classes into cpp to shorten build times when working on them.
-Remove default param values for IterOpenCLKernelCreator<T>::SharedDataIndexDefines in cpp file.
-Change more NULL to nullptr.
2017-02-26 03:02:21 -05:00
size_t row = j * m_SuperRasW ;
size_t rowEnd = row + endCol ;
2014-09-10 01:41:26 -04:00
--User changes
-Add a palette editor.
-Add support for reading .ugr/.gradient/.gradients palette files.
-Allow toggling on spinners whose minimum value is not zero.
-Allow toggling display of image, affines and grid.
-Add new variations: cylinder2, circlesplit, tile_log, truchet_fill, waves2_radial.
--Bug fixes
-cpow2 was wrong.
-Palettes with rapid changes in color would produce slightly different outputs from Apo/Chaotica. This was due to a long standing bug from flam3.
-Use exec() on Apple and show() on all other OSes for dialog boxes.
-Trying to render a sequence with no frames would crash.
-Selecting multiple xforms and rotating them would produce the wrong rotation.
-Better handling when parsing flames using different encoding, such as unicode and UTF-8.
-Switching between SP/DP didn't reselect the selected flame in the Library tab.
--Code changes
-Make all types concerning palettes be floats, including PaletteTableWidgetItem.
-PaletteTableWidgetItem is no longer templated because all palettes are float.
-Include the source colors for user created gradients.
-Change parallel_for() calls to work with very old versions of TBB which are lingering on some systems.
-Split conditional out of accumulation loop on the CPU for better performance.
-Vectorize summing when doing density filter for better performance.
-Make all usage of palettes be of type float, double is pointless.
-Allow palettes to reside in multiple folders, while ensuring only one of each name is added.
-Refactor some palette path searching code.
-Make ReadFile() throw and catch an exception if the file operation fails.
-A little extra safety in foci and foci3D with a call to Zeps().
-Cast to (real_t) in the OpenCL string for the w variation, which was having trouble compiling on Mac.
-Fixing missing comma between paths in InitPaletteList().
-Move Xml and PaletteList classes into cpp to shorten build times when working on them.
-Remove default param values for IterOpenCLKernelCreator<T>::SharedDataIndexDefines in cpp file.
-Change more NULL to nullptr.
2017-02-26 03:02:21 -05:00
if ( ! m_Abort )
{
for ( size_t i = row ; i < rowEnd ; i + + )
2014-07-08 03:11:14 -04:00
{
--User changes
-Add a palette editor.
-Add support for reading .ugr/.gradient/.gradients palette files.
-Allow toggling on spinners whose minimum value is not zero.
-Allow toggling display of image, affines and grid.
-Add new variations: cylinder2, circlesplit, tile_log, truchet_fill, waves2_radial.
--Bug fixes
-cpow2 was wrong.
-Palettes with rapid changes in color would produce slightly different outputs from Apo/Chaotica. This was due to a long standing bug from flam3.
-Use exec() on Apple and show() on all other OSes for dialog boxes.
-Trying to render a sequence with no frames would crash.
-Selecting multiple xforms and rotating them would produce the wrong rotation.
-Better handling when parsing flames using different encoding, such as unicode and UTF-8.
-Switching between SP/DP didn't reselect the selected flame in the Library tab.
--Code changes
-Make all types concerning palettes be floats, including PaletteTableWidgetItem.
-PaletteTableWidgetItem is no longer templated because all palettes are float.
-Include the source colors for user created gradients.
-Change parallel_for() calls to work with very old versions of TBB which are lingering on some systems.
-Split conditional out of accumulation loop on the CPU for better performance.
-Vectorize summing when doing density filter for better performance.
-Make all usage of palettes be of type float, double is pointless.
-Allow palettes to reside in multiple folders, while ensuring only one of each name is added.
-Refactor some palette path searching code.
-Make ReadFile() throw and catch an exception if the file operation fails.
-A little extra safety in foci and foci3D with a call to Zeps().
-Cast to (real_t) in the OpenCL string for the w variation, which was having trouble compiling on Mac.
-Fixing missing comma between paths in InitPaletteList().
-Move Xml and PaletteList classes into cpp to shorten build times when working on them.
-Remove default param values for IterOpenCLKernelCreator<T>::SharedDataIndexDefines in cpp file.
-Change more NULL to nullptr.
2017-02-26 03:02:21 -05:00
//Check for visibility first before doing anything else to avoid all possible unnecessary calculations.
if ( m_HistBuckets [ i ] . a ! = 0 )
--User changes
-Add new variations: bubbleT3D, crob, hexaplay3D, hexcrop, hexes, hexnix3D, loonie2, loonie3, nBlur, octapol and synth.
-Allow for pre/post versions of dc_bubble, dc_cylinder and dc_linear whereas before they were omitted.
-When saving a file with multiple embers in it, detect if time values are all the same and if so, start them at zero and increment by 1 for each ember.
-Allow for numerous quality increases to be coalesced into one. It will pick up at the end of the current render.
-Show selection highlight on variations tree in response to mouse hover. This makes it easier to see for which variation or param the current mouse wheel action will apply.
-Make default temporal samples be 100, whereas before it was 1000 which was overkill.
-Require the shift key to be held with delete for deleting an ember to prevent it from triggering when the user enters delete in the edit box.
-This wasn't otherwise fixable without writing a lot more code.
--Bug fixes
-EmberGenome was crashing when generating a sequence from a source file with more than 2 embers in it.
-EmberGenome was improperly handling the first frame of a merge after the last frame of the loop.
-These bugs were due to a previous commit. Revert parts of that commit.
-Prevent a zoom value of less than 0 when reading from xml.
-Slight optimization of the crescents, and mask variations, if the compiler wasn't doing it already.
-Unique file naming was broken because it was looking for _# and the default names ended with -#.
-Disallow renaming of an ember in the library tree to an empty string.
-Severe bug that prevented some variations from being read correctly from params generated outside this program.
-Severe OpenCL randomization bug. The first x coordinates of the first points in the first kernel call of the first ember of a render since the OpenCL renderer object was created were not random and were mostly -1.
-Severe bug when populating xform selection distributions that could sometimes cause a crash due to roundoff error. Fix by using double.
-Limit the max number of variations in a random ember to MAX_CL_VARS, which is 8. This ensures they'll look the same on CPU and GPU.
-Prevent user from saving stylesheet to default.qss, it's a special reserved filename.
--Code changes
-Generalize using the running sum output point inside of a variation for all cases: pre, reg and post.
-Allow for array variables in variations where the address of each element is stored in m_Params.
-Qualify all math functions with std::
-No longer use our own Clamp() in OpenCL, instead use the standard clamp().
-Redesign how functions are used in the variations OpenCL code.
-Add tests to EmberTester to verify some of the new functionality.
-Place more const and override qualifiers on functions where appropriate.
-Add a global rand with a lock to be used very sparingly.
-Use a map instead of a vector for bad param names in Xml parsing.
-Prefix affine interpolation mode defines with "AFFINE_" to make their purpose more clear.
-Allow for variations that change state during iteration by sending a separate copy of the ember to each rendering thread.
-Implement this same functionality with a local struct in OpenCL. It's members are the total of all variables that need to change state within an ember.
-Add Contains() function to Utils.h.
-EmberRender: print names of kernels being printed with --dump_kernel option.
-Clean up EmberTester to handle some of the recent changes.
-Fix various casts.
-Replace % 2 with & 1, even though the compiler was likely doing this already.
-Add new file Variations06.h to accommodate new variations.
-General cleanup.
2015-11-22 17:15:07 -05:00
{
--User changes
-Add a palette editor.
-Add support for reading .ugr/.gradient/.gradients palette files.
-Allow toggling on spinners whose minimum value is not zero.
-Allow toggling display of image, affines and grid.
-Add new variations: cylinder2, circlesplit, tile_log, truchet_fill, waves2_radial.
--Bug fixes
-cpow2 was wrong.
-Palettes with rapid changes in color would produce slightly different outputs from Apo/Chaotica. This was due to a long standing bug from flam3.
-Use exec() on Apple and show() on all other OSes for dialog boxes.
-Trying to render a sequence with no frames would crash.
-Selecting multiple xforms and rotating them would produce the wrong rotation.
-Better handling when parsing flames using different encoding, such as unicode and UTF-8.
-Switching between SP/DP didn't reselect the selected flame in the Library tab.
--Code changes
-Make all types concerning palettes be floats, including PaletteTableWidgetItem.
-PaletteTableWidgetItem is no longer templated because all palettes are float.
-Include the source colors for user created gradients.
-Change parallel_for() calls to work with very old versions of TBB which are lingering on some systems.
-Split conditional out of accumulation loop on the CPU for better performance.
-Vectorize summing when doing density filter for better performance.
-Make all usage of palettes be of type float, double is pointless.
-Allow palettes to reside in multiple folders, while ensuring only one of each name is added.
-Refactor some palette path searching code.
-Make ReadFile() throw and catch an exception if the file operation fails.
-A little extra safety in foci and foci3D with a call to Zeps().
-Cast to (real_t) in the OpenCL string for the w variation, which was having trouble compiling on Mac.
-Fixing missing comma between paths in InitPaletteList().
-Move Xml and PaletteList classes into cpp to shorten build times when working on them.
-Remove default param values for IterOpenCLKernelCreator<T>::SharedDataIndexDefines in cpp file.
-Change more NULL to nullptr.
2017-02-26 03:02:21 -05:00
bucketT logScale = ( m_K1 * std : : log ( 1 + m_HistBuckets [ i ] . a * m_K2 ) ) / m_HistBuckets [ i ] . a ;
//Original did a temporary assignment, then *= logScale, then passed the result to bump_no_overflow().
//Combine here into one operation for a slight speedup.
//Vectorized version:
bucketT * __restrict hist = glm : : value_ptr ( m_HistBuckets [ i ] ) ; //Vectorizer can't tell these point to different locations.
bucketT * __restrict acc = glm : : value_ptr ( m_AccumulatorBuckets [ i ] ) ;
2017-07-22 16:43:35 -04:00
for ( size_t v = 0 ; v < 4 ; v + + ) //Vectorized by compiler.
--User changes
-Add a palette editor.
-Add support for reading .ugr/.gradient/.gradients palette files.
-Allow toggling on spinners whose minimum value is not zero.
-Allow toggling display of image, affines and grid.
-Add new variations: cylinder2, circlesplit, tile_log, truchet_fill, waves2_radial.
--Bug fixes
-cpow2 was wrong.
-Palettes with rapid changes in color would produce slightly different outputs from Apo/Chaotica. This was due to a long standing bug from flam3.
-Use exec() on Apple and show() on all other OSes for dialog boxes.
-Trying to render a sequence with no frames would crash.
-Selecting multiple xforms and rotating them would produce the wrong rotation.
-Better handling when parsing flames using different encoding, such as unicode and UTF-8.
-Switching between SP/DP didn't reselect the selected flame in the Library tab.
--Code changes
-Make all types concerning palettes be floats, including PaletteTableWidgetItem.
-PaletteTableWidgetItem is no longer templated because all palettes are float.
-Include the source colors for user created gradients.
-Change parallel_for() calls to work with very old versions of TBB which are lingering on some systems.
-Split conditional out of accumulation loop on the CPU for better performance.
-Vectorize summing when doing density filter for better performance.
-Make all usage of palettes be of type float, double is pointless.
-Allow palettes to reside in multiple folders, while ensuring only one of each name is added.
-Refactor some palette path searching code.
-Make ReadFile() throw and catch an exception if the file operation fails.
-A little extra safety in foci and foci3D with a call to Zeps().
-Cast to (real_t) in the OpenCL string for the w variation, which was having trouble compiling on Mac.
-Fixing missing comma between paths in InitPaletteList().
-Move Xml and PaletteList classes into cpp to shorten build times when working on them.
-Remove default param values for IterOpenCLKernelCreator<T>::SharedDataIndexDefines in cpp file.
-Change more NULL to nullptr.
2017-02-26 03:02:21 -05:00
acc [ v ] = hist [ v ] * logScale ;
--User changes
-Add new variations: bubbleT3D, crob, hexaplay3D, hexcrop, hexes, hexnix3D, loonie2, loonie3, nBlur, octapol and synth.
-Allow for pre/post versions of dc_bubble, dc_cylinder and dc_linear whereas before they were omitted.
-When saving a file with multiple embers in it, detect if time values are all the same and if so, start them at zero and increment by 1 for each ember.
-Allow for numerous quality increases to be coalesced into one. It will pick up at the end of the current render.
-Show selection highlight on variations tree in response to mouse hover. This makes it easier to see for which variation or param the current mouse wheel action will apply.
-Make default temporal samples be 100, whereas before it was 1000 which was overkill.
-Require the shift key to be held with delete for deleting an ember to prevent it from triggering when the user enters delete in the edit box.
-This wasn't otherwise fixable without writing a lot more code.
--Bug fixes
-EmberGenome was crashing when generating a sequence from a source file with more than 2 embers in it.
-EmberGenome was improperly handling the first frame of a merge after the last frame of the loop.
-These bugs were due to a previous commit. Revert parts of that commit.
-Prevent a zoom value of less than 0 when reading from xml.
-Slight optimization of the crescents, and mask variations, if the compiler wasn't doing it already.
-Unique file naming was broken because it was looking for _# and the default names ended with -#.
-Disallow renaming of an ember in the library tree to an empty string.
-Severe bug that prevented some variations from being read correctly from params generated outside this program.
-Severe OpenCL randomization bug. The first x coordinates of the first points in the first kernel call of the first ember of a render since the OpenCL renderer object was created were not random and were mostly -1.
-Severe bug when populating xform selection distributions that could sometimes cause a crash due to roundoff error. Fix by using double.
-Limit the max number of variations in a random ember to MAX_CL_VARS, which is 8. This ensures they'll look the same on CPU and GPU.
-Prevent user from saving stylesheet to default.qss, it's a special reserved filename.
--Code changes
-Generalize using the running sum output point inside of a variation for all cases: pre, reg and post.
-Allow for array variables in variations where the address of each element is stored in m_Params.
-Qualify all math functions with std::
-No longer use our own Clamp() in OpenCL, instead use the standard clamp().
-Redesign how functions are used in the variations OpenCL code.
-Add tests to EmberTester to verify some of the new functionality.
-Place more const and override qualifiers on functions where appropriate.
-Add a global rand with a lock to be used very sparingly.
-Use a map instead of a vector for bad param names in Xml parsing.
-Prefix affine interpolation mode defines with "AFFINE_" to make their purpose more clear.
-Allow for variations that change state during iteration by sending a separate copy of the ember to each rendering thread.
-Implement this same functionality with a local struct in OpenCL. It's members are the total of all variables that need to change state within an ember.
-Add Contains() function to Utils.h.
-EmberRender: print names of kernels being printed with --dump_kernel option.
-Clean up EmberTester to handle some of the recent changes.
-Fix various casts.
-Replace % 2 with & 1, even though the compiler was likely doing this already.
-Add new file Variations06.h to accommodate new variations.
-General cleanup.
2015-11-22 17:15:07 -05:00
}
2014-07-08 03:11:14 -04:00
}
--User changes
-Add a palette editor.
-Add support for reading .ugr/.gradient/.gradients palette files.
-Allow toggling on spinners whose minimum value is not zero.
-Allow toggling display of image, affines and grid.
-Add new variations: cylinder2, circlesplit, tile_log, truchet_fill, waves2_radial.
--Bug fixes
-cpow2 was wrong.
-Palettes with rapid changes in color would produce slightly different outputs from Apo/Chaotica. This was due to a long standing bug from flam3.
-Use exec() on Apple and show() on all other OSes for dialog boxes.
-Trying to render a sequence with no frames would crash.
-Selecting multiple xforms and rotating them would produce the wrong rotation.
-Better handling when parsing flames using different encoding, such as unicode and UTF-8.
-Switching between SP/DP didn't reselect the selected flame in the Library tab.
--Code changes
-Make all types concerning palettes be floats, including PaletteTableWidgetItem.
-PaletteTableWidgetItem is no longer templated because all palettes are float.
-Include the source colors for user created gradients.
-Change parallel_for() calls to work with very old versions of TBB which are lingering on some systems.
-Split conditional out of accumulation loop on the CPU for better performance.
-Vectorize summing when doing density filter for better performance.
-Make all usage of palettes be of type float, double is pointless.
-Allow palettes to reside in multiple folders, while ensuring only one of each name is added.
-Refactor some palette path searching code.
-Make ReadFile() throw and catch an exception if the file operation fails.
-A little extra safety in foci and foci3D with a call to Zeps().
-Cast to (real_t) in the OpenCL string for the w variation, which was having trouble compiling on Mac.
-Fixing missing comma between paths in InitPaletteList().
-Move Xml and PaletteList classes into cpp to shorten build times when working on them.
-Remove default param values for IterOpenCLKernelCreator<T>::SharedDataIndexDefines in cpp file.
-Change more NULL to nullptr.
2017-02-26 03:02:21 -05:00
}
2017-08-28 23:45:58 -04:00
}
# if defined(_WIN32) || defined(__APPLE__)
, tbb : : static_partitioner ( )
# endif
) ;
2017-09-03 02:01:10 -04:00
if ( m_Callback & & ! m_Abort )
if ( ! m_Callback - > ProgressFunc ( m_Ember , m_ProgressParameter , 100.0 , 1 , 0 ) )
Abort ( ) ;
2014-07-08 03:11:14 -04:00
//t.Toc(__FUNCTION__);
2015-12-31 19:00:36 -05:00
return m_Abort ? eRenderStatus : : RENDER_ABORT : eRenderStatus : : RENDER_OK ;
2014-07-08 03:11:14 -04:00
}
/// <summary>
/// Perform the more advanced Gaussian density filter.
/// More advanced density estimation filtering given less mention in the paper, but used
/// much more in practice as it gives the best results.
/// Section 8, p. 11-13.
/// </summary>
/// <returns>True if not prematurely aborted, else false.</returns>
template < typename T , typename bucketT >
eRenderStatus Renderer < T , bucketT > : : GaussianDensityFilter ( )
{
Timing totalTime , localTime ;
2014-10-14 11:53:15 -04:00
bool scf = ! ( Supersample ( ) & 1 ) ;
intmax_t ss = Floor < T > ( Supersample ( ) / T ( 2 ) ) ;
--User changes
-Add new variations: bubbleT3D, crob, hexaplay3D, hexcrop, hexes, hexnix3D, loonie2, loonie3, nBlur, octapol and synth.
-Allow for pre/post versions of dc_bubble, dc_cylinder and dc_linear whereas before they were omitted.
-When saving a file with multiple embers in it, detect if time values are all the same and if so, start them at zero and increment by 1 for each ember.
-Allow for numerous quality increases to be coalesced into one. It will pick up at the end of the current render.
-Show selection highlight on variations tree in response to mouse hover. This makes it easier to see for which variation or param the current mouse wheel action will apply.
-Make default temporal samples be 100, whereas before it was 1000 which was overkill.
-Require the shift key to be held with delete for deleting an ember to prevent it from triggering when the user enters delete in the edit box.
-This wasn't otherwise fixable without writing a lot more code.
--Bug fixes
-EmberGenome was crashing when generating a sequence from a source file with more than 2 embers in it.
-EmberGenome was improperly handling the first frame of a merge after the last frame of the loop.
-These bugs were due to a previous commit. Revert parts of that commit.
-Prevent a zoom value of less than 0 when reading from xml.
-Slight optimization of the crescents, and mask variations, if the compiler wasn't doing it already.
-Unique file naming was broken because it was looking for _# and the default names ended with -#.
-Disallow renaming of an ember in the library tree to an empty string.
-Severe bug that prevented some variations from being read correctly from params generated outside this program.
-Severe OpenCL randomization bug. The first x coordinates of the first points in the first kernel call of the first ember of a render since the OpenCL renderer object was created were not random and were mostly -1.
-Severe bug when populating xform selection distributions that could sometimes cause a crash due to roundoff error. Fix by using double.
-Limit the max number of variations in a random ember to MAX_CL_VARS, which is 8. This ensures they'll look the same on CPU and GPU.
-Prevent user from saving stylesheet to default.qss, it's a special reserved filename.
--Code changes
-Generalize using the running sum output point inside of a variation for all cases: pre, reg and post.
-Allow for array variables in variations where the address of each element is stored in m_Params.
-Qualify all math functions with std::
-No longer use our own Clamp() in OpenCL, instead use the standard clamp().
-Redesign how functions are used in the variations OpenCL code.
-Add tests to EmberTester to verify some of the new functionality.
-Place more const and override qualifiers on functions where appropriate.
-Add a global rand with a lock to be used very sparingly.
-Use a map instead of a vector for bad param names in Xml parsing.
-Prefix affine interpolation mode defines with "AFFINE_" to make their purpose more clear.
-Allow for variations that change state during iteration by sending a separate copy of the ember to each rendering thread.
-Implement this same functionality with a local struct in OpenCL. It's members are the total of all variables that need to change state within an ember.
-Add Contains() function to Utils.h.
-EmberRender: print names of kernels being printed with --dump_kernel option.
-Clean up EmberTester to handle some of the recent changes.
-Fix various casts.
-Replace % 2 with & 1, even though the compiler was likely doing this already.
-Add new file Variations06.h to accommodate new variations.
-General cleanup.
2015-11-22 17:15:07 -05:00
T scfact = std : : pow ( Supersample ( ) / ( Supersample ( ) + T ( 1 ) ) , T ( 2 ) ) ;
2014-10-14 11:53:15 -04:00
size_t threads = m_ThreadsToUse ;
size_t startRow = Supersample ( ) - 1 ;
size_t endRow = m_SuperRasH - ( Supersample ( ) - 1 ) ; //Original did + which is most likely wrong.
intmax_t startCol = Supersample ( ) - 1 ;
intmax_t endCol = m_SuperRasW - ( Supersample ( ) - 1 ) ;
2014-12-07 02:51:44 -05:00
size_t chunkSize = size_t ( ceil ( double ( endRow - startRow ) / double ( threads ) ) ) ;
2014-07-08 03:11:14 -04:00
//parallel_for scales very well, dividing the work almost perfectly among all processors.
--User changes
-Add a palette editor.
-Add support for reading .ugr/.gradient/.gradients palette files.
-Allow toggling on spinners whose minimum value is not zero.
-Allow toggling display of image, affines and grid.
-Add new variations: cylinder2, circlesplit, tile_log, truchet_fill, waves2_radial.
--Bug fixes
-cpow2 was wrong.
-Palettes with rapid changes in color would produce slightly different outputs from Apo/Chaotica. This was due to a long standing bug from flam3.
-Use exec() on Apple and show() on all other OSes for dialog boxes.
-Trying to render a sequence with no frames would crash.
-Selecting multiple xforms and rotating them would produce the wrong rotation.
-Better handling when parsing flames using different encoding, such as unicode and UTF-8.
-Switching between SP/DP didn't reselect the selected flame in the Library tab.
--Code changes
-Make all types concerning palettes be floats, including PaletteTableWidgetItem.
-PaletteTableWidgetItem is no longer templated because all palettes are float.
-Include the source colors for user created gradients.
-Change parallel_for() calls to work with very old versions of TBB which are lingering on some systems.
-Split conditional out of accumulation loop on the CPU for better performance.
-Vectorize summing when doing density filter for better performance.
-Make all usage of palettes be of type float, double is pointless.
-Allow palettes to reside in multiple folders, while ensuring only one of each name is added.
-Refactor some palette path searching code.
-Make ReadFile() throw and catch an exception if the file operation fails.
-A little extra safety in foci and foci3D with a call to Zeps().
-Cast to (real_t) in the OpenCL string for the w variation, which was having trouble compiling on Mac.
-Fixing missing comma between paths in InitPaletteList().
-Move Xml and PaletteList classes into cpp to shorten build times when working on them.
-Remove default param values for IterOpenCLKernelCreator<T>::SharedDataIndexDefines in cpp file.
-Change more NULL to nullptr.
2017-02-26 03:02:21 -05:00
parallel_for ( size_t ( 0 ) , threads , size_t ( 1 ) , [ & ] ( size_t threadIndex )
2014-07-08 03:11:14 -04:00
{
2014-10-14 11:53:15 -04:00
size_t pixelNumber = 0 ;
2015-03-21 18:27:37 -04:00
int localStartRow = int ( std : : min < size_t > ( startRow + ( threadIndex * chunkSize ) , endRow - 1 ) ) ;
int localEndRow = int ( std : : min < size_t > ( localStartRow + chunkSize , endRow ) ) ;
2014-10-14 11:53:15 -04:00
size_t pixelsThisThread = size_t ( localEndRow - localStartRow ) * m_SuperRasW ;
2014-07-08 03:11:14 -04:00
double lastPercent = 0 ;
2015-03-21 18:27:37 -04:00
tvec4 < bucketT , glm : : defaultp > logScaleBucket ;
2014-10-15 11:19:59 -04:00
2014-10-14 11:53:15 -04:00
for ( intmax_t j = localStartRow ; ( j < localEndRow ) & & ! m_Abort ; j + + )
2014-07-08 03:11:14 -04:00
{
06/09/2017
--User changes
-dark.qss is now per-OS.
-Properly set/reload palette when coming from the palette editor. The latter must be done if they've modified the current palette even if they've clicked cancel.
--Bug fixes
-Make the following variations safer by using Zeps(): conic, bipolar, edisc, whorl, tan, csc, cot, tanh, sech, csch, coth, auger, bwraps, hypertile3d, hypertile3d1, ortho, poincare, rational3, barycentroid, sschecks, cscq, cschq, scry_3D, splitbrdr, hexcrop, nblur, crob.
-Fix bug enabling/disabling overwrite button in palette editor.
-Small optimization for gdoffs, use precalcAtanYX.
-Properly propagate z through circlesplit, cylinder2 and tile_log variations.
-Some values in truchet_fill could've been NaN.
--Code changes
-Make most installation files read only.
-Qualify many calls with std:: to ensure they're not colliding with glm::
-Use auto in more places.
2017-06-09 22:38:06 -04:00
auto buckets = m_HistBuckets . data ( ) ;
auto bucketRowStart = buckets + ( j * m_SuperRasW ) ; //Pull out of inner loop for optimization.
auto filterCoefs = m_DensityFilter - > Coefs ( ) ;
auto filterWidths = m_DensityFilter - > Widths ( ) ;
2014-10-15 11:19:59 -04:00
2014-10-14 11:53:15 -04:00
for ( intmax_t i = startCol ; i < endCol ; i + + )
2014-07-08 03:11:14 -04:00
{
2014-10-14 11:53:15 -04:00
intmax_t ii , jj , arrFilterWidth ;
size_t filterSelectInt , filterCoefIndex ;
2014-07-08 03:11:14 -04:00
T filterSelect = 0 ;
06/09/2017
--User changes
-dark.qss is now per-OS.
-Properly set/reload palette when coming from the palette editor. The latter must be done if they've modified the current palette even if they've clicked cancel.
--Bug fixes
-Make the following variations safer by using Zeps(): conic, bipolar, edisc, whorl, tan, csc, cot, tanh, sech, csch, coth, auger, bwraps, hypertile3d, hypertile3d1, ortho, poincare, rational3, barycentroid, sschecks, cscq, cschq, scry_3D, splitbrdr, hexcrop, nblur, crob.
-Fix bug enabling/disabling overwrite button in palette editor.
-Small optimization for gdoffs, use precalcAtanYX.
-Properly propagate z through circlesplit, cylinder2 and tile_log variations.
-Some values in truchet_fill could've been NaN.
--Code changes
-Make most installation files read only.
-Qualify many calls with std:: to ensure they're not colliding with glm::
-Use auto in more places.
2017-06-09 22:38:06 -04:00
auto bucket = bucketRowStart + i ;
2014-10-15 11:19:59 -04:00
2014-07-08 03:11:14 -04:00
//Don't do anything if there's no hits here. Must also put this first to avoid dividing by zero below.
if ( bucket - > a = = 0 )
continue ;
2014-10-15 11:19:59 -04:00
--User changes
-Add new variations: bubbleT3D, crob, hexaplay3D, hexcrop, hexes, hexnix3D, loonie2, loonie3, nBlur, octapol and synth.
-Allow for pre/post versions of dc_bubble, dc_cylinder and dc_linear whereas before they were omitted.
-When saving a file with multiple embers in it, detect if time values are all the same and if so, start them at zero and increment by 1 for each ember.
-Allow for numerous quality increases to be coalesced into one. It will pick up at the end of the current render.
-Show selection highlight on variations tree in response to mouse hover. This makes it easier to see for which variation or param the current mouse wheel action will apply.
-Make default temporal samples be 100, whereas before it was 1000 which was overkill.
-Require the shift key to be held with delete for deleting an ember to prevent it from triggering when the user enters delete in the edit box.
-This wasn't otherwise fixable without writing a lot more code.
--Bug fixes
-EmberGenome was crashing when generating a sequence from a source file with more than 2 embers in it.
-EmberGenome was improperly handling the first frame of a merge after the last frame of the loop.
-These bugs were due to a previous commit. Revert parts of that commit.
-Prevent a zoom value of less than 0 when reading from xml.
-Slight optimization of the crescents, and mask variations, if the compiler wasn't doing it already.
-Unique file naming was broken because it was looking for _# and the default names ended with -#.
-Disallow renaming of an ember in the library tree to an empty string.
-Severe bug that prevented some variations from being read correctly from params generated outside this program.
-Severe OpenCL randomization bug. The first x coordinates of the first points in the first kernel call of the first ember of a render since the OpenCL renderer object was created were not random and were mostly -1.
-Severe bug when populating xform selection distributions that could sometimes cause a crash due to roundoff error. Fix by using double.
-Limit the max number of variations in a random ember to MAX_CL_VARS, which is 8. This ensures they'll look the same on CPU and GPU.
-Prevent user from saving stylesheet to default.qss, it's a special reserved filename.
--Code changes
-Generalize using the running sum output point inside of a variation for all cases: pre, reg and post.
-Allow for array variables in variations where the address of each element is stored in m_Params.
-Qualify all math functions with std::
-No longer use our own Clamp() in OpenCL, instead use the standard clamp().
-Redesign how functions are used in the variations OpenCL code.
-Add tests to EmberTester to verify some of the new functionality.
-Place more const and override qualifiers on functions where appropriate.
-Add a global rand with a lock to be used very sparingly.
-Use a map instead of a vector for bad param names in Xml parsing.
-Prefix affine interpolation mode defines with "AFFINE_" to make their purpose more clear.
-Allow for variations that change state during iteration by sending a separate copy of the ember to each rendering thread.
-Implement this same functionality with a local struct in OpenCL. It's members are the total of all variables that need to change state within an ember.
-Add Contains() function to Utils.h.
-EmberRender: print names of kernels being printed with --dump_kernel option.
-Clean up EmberTester to handle some of the recent changes.
-Fix various casts.
-Replace % 2 with & 1, even though the compiler was likely doing this already.
-Add new file Variations06.h to accommodate new variations.
-General cleanup.
2015-11-22 17:15:07 -05:00
bucketT cacheLog = ( m_K1 * std : : log ( 1 + bucket - > a * m_K2 ) ) / bucket - > a ; //Caching this calculation gives a 30% speedup.
2014-10-15 11:19:59 -04:00
2014-07-08 03:11:14 -04:00
if ( ss = = 0 )
{
filterSelect = bucket - > a ;
}
else
{
//The original contained a glaring flaw as it would run past the boundaries of the buffers
//when calculating the density for a box centered on the last row or column.
//Clamp here to not run over the edge.
2015-03-21 18:27:37 -04:00
intmax_t densityBoxLeftX = ( i - std : : min ( i , ss ) ) ;
intmax_t densityBoxRightX = ( i + std : : min ( ss , intmax_t ( m_SuperRasW ) - i - 1 ) ) ;
intmax_t densityBoxTopY = ( j - std : : min ( j , ss ) ) ;
intmax_t densityBoxBottomY = ( j + std : : min ( ss , intmax_t ( m_SuperRasH ) - j - 1 ) ) ;
2014-10-15 11:19:59 -04:00
2014-07-08 03:11:14 -04:00
//Count density in ssxss area.
//Original went one col at a time, which is cache inefficient. Go one row at at time here for a slight speedup.
for ( jj = densityBoxTopY ; jj < = densityBoxBottomY ; jj + + )
for ( ii = densityBoxLeftX ; ii < = densityBoxRightX ; ii + + )
filterSelect + = buckets [ ii + ( jj * m_SuperRasW ) ] . a ; //Original divided by 255 in every iteration. Omit here because colors are already in the range of [0..1].
}
2014-10-15 11:19:59 -04:00
2014-07-08 03:11:14 -04:00
//Scale if supersample > 1 for equal iters.
if ( scf )
filterSelect * = scfact ;
2014-10-15 11:19:59 -04:00
2014-07-08 03:11:14 -04:00
if ( filterSelect > m_DensityFilter - > MaxFilteredCounts ( ) )
filterSelectInt = m_DensityFilter - > MaxFilterIndex ( ) ;
else if ( filterSelect < = DE_THRESH )
2014-12-07 02:51:44 -05:00
filterSelectInt = size_t ( ceil ( filterSelect ) ) - 1 ;
2014-07-08 03:11:14 -04:00
else
--User changes
-Add new variations: bubbleT3D, crob, hexaplay3D, hexcrop, hexes, hexnix3D, loonie2, loonie3, nBlur, octapol and synth.
-Allow for pre/post versions of dc_bubble, dc_cylinder and dc_linear whereas before they were omitted.
-When saving a file with multiple embers in it, detect if time values are all the same and if so, start them at zero and increment by 1 for each ember.
-Allow for numerous quality increases to be coalesced into one. It will pick up at the end of the current render.
-Show selection highlight on variations tree in response to mouse hover. This makes it easier to see for which variation or param the current mouse wheel action will apply.
-Make default temporal samples be 100, whereas before it was 1000 which was overkill.
-Require the shift key to be held with delete for deleting an ember to prevent it from triggering when the user enters delete in the edit box.
-This wasn't otherwise fixable without writing a lot more code.
--Bug fixes
-EmberGenome was crashing when generating a sequence from a source file with more than 2 embers in it.
-EmberGenome was improperly handling the first frame of a merge after the last frame of the loop.
-These bugs were due to a previous commit. Revert parts of that commit.
-Prevent a zoom value of less than 0 when reading from xml.
-Slight optimization of the crescents, and mask variations, if the compiler wasn't doing it already.
-Unique file naming was broken because it was looking for _# and the default names ended with -#.
-Disallow renaming of an ember in the library tree to an empty string.
-Severe bug that prevented some variations from being read correctly from params generated outside this program.
-Severe OpenCL randomization bug. The first x coordinates of the first points in the first kernel call of the first ember of a render since the OpenCL renderer object was created were not random and were mostly -1.
-Severe bug when populating xform selection distributions that could sometimes cause a crash due to roundoff error. Fix by using double.
-Limit the max number of variations in a random ember to MAX_CL_VARS, which is 8. This ensures they'll look the same on CPU and GPU.
-Prevent user from saving stylesheet to default.qss, it's a special reserved filename.
--Code changes
-Generalize using the running sum output point inside of a variation for all cases: pre, reg and post.
-Allow for array variables in variations where the address of each element is stored in m_Params.
-Qualify all math functions with std::
-No longer use our own Clamp() in OpenCL, instead use the standard clamp().
-Redesign how functions are used in the variations OpenCL code.
-Add tests to EmberTester to verify some of the new functionality.
-Place more const and override qualifiers on functions where appropriate.
-Add a global rand with a lock to be used very sparingly.
-Use a map instead of a vector for bad param names in Xml parsing.
-Prefix affine interpolation mode defines with "AFFINE_" to make their purpose more clear.
-Allow for variations that change state during iteration by sending a separate copy of the ember to each rendering thread.
-Implement this same functionality with a local struct in OpenCL. It's members are the total of all variables that need to change state within an ember.
-Add Contains() function to Utils.h.
-EmberRender: print names of kernels being printed with --dump_kernel option.
-Clean up EmberTester to handle some of the recent changes.
-Fix various casts.
-Replace % 2 with & 1, even though the compiler was likely doing this already.
-Add new file Variations06.h to accommodate new variations.
-General cleanup.
2015-11-22 17:15:07 -05:00
filterSelectInt = DE_THRESH + size_t ( Floor < T > ( std : : pow ( filterSelect - DE_THRESH , m_DensityFilter - > Curve ( ) ) ) ) ;
2014-10-15 11:19:59 -04:00
2014-07-08 03:11:14 -04:00
//If the filter selected below the min specified clamp it to the min.
if ( filterSelectInt > m_DensityFilter - > MaxFilterIndex ( ) )
filterSelectInt = m_DensityFilter - > MaxFilterIndex ( ) ;
2014-10-15 11:19:59 -04:00
2014-07-08 03:11:14 -04:00
//Only have to calculate the values for ~1/8 of the square.
filterCoefIndex = filterSelectInt * m_DensityFilter - > KernelSize ( ) ;
2014-12-07 02:51:44 -05:00
arrFilterWidth = intmax_t ( ceil ( filterWidths [ filterSelectInt ] ) ) - 1 ;
2014-10-15 11:19:59 -04:00
2014-07-08 03:11:14 -04:00
for ( jj = 0 ; jj < = arrFilterWidth ; jj + + )
{
for ( ii = 0 ; ii < = jj ; ii + + , filterCoefIndex + + )
{
//Skip if coef is 0.
if ( filterCoefs [ filterCoefIndex ] = = 0 )
continue ;
2014-10-15 11:19:59 -04:00
2015-08-10 23:10:23 -04:00
bucketT logScale = filterCoefs [ filterCoefIndex ] * cacheLog ;
2014-07-08 03:11:14 -04:00
//Original first assigned the fields, then scaled them. Combine into a single step for a 1% optimization.
2015-08-10 23:10:23 -04:00
logScaleBucket = ( * bucket * logScale ) ;
2014-10-15 11:19:59 -04:00
2014-07-08 03:11:14 -04:00
if ( jj = = 0 & & ii = = 0 )
{
AddToAccum ( logScaleBucket , i , ii , j , jj ) ;
}
else if ( ii = = 0 )
{
AddToAccum ( logScaleBucket , i , 0 , j , - jj ) ;
AddToAccum ( logScaleBucket , i , - jj , j , 0 ) ;
AddToAccum ( logScaleBucket , i , jj , j , 0 ) ;
AddToAccum ( logScaleBucket , i , 0 , j , jj ) ;
}
else if ( jj = = ii )
{
AddToAccum ( logScaleBucket , i , - ii , j , - jj ) ;
AddToAccum ( logScaleBucket , i , ii , j , - jj ) ;
AddToAccum ( logScaleBucket , i , - ii , j , jj ) ;
AddToAccum ( logScaleBucket , i , ii , j , jj ) ;
}
else
{
//Attempting to optimize cache access by putting these in order makes no difference, even on large images, but do it anyway.
AddToAccum ( logScaleBucket , i , - ii , j , - jj ) ;
AddToAccum ( logScaleBucket , i , ii , j , - jj ) ;
AddToAccum ( logScaleBucket , i , - jj , j , - ii ) ;
AddToAccum ( logScaleBucket , i , jj , j , - ii ) ;
AddToAccum ( logScaleBucket , i , - jj , j , ii ) ;
AddToAccum ( logScaleBucket , i , jj , j , ii ) ;
AddToAccum ( logScaleBucket , i , - ii , j , jj ) ;
AddToAccum ( logScaleBucket , i , ii , j , jj ) ;
}
}
}
}
2014-10-15 11:19:59 -04:00
2014-07-08 03:11:14 -04:00
if ( m_Callback & & threadIndex = = 0 )
{
pixelNumber + = m_SuperRasW ;
double percent = ( double ( pixelNumber ) / double ( pixelsThisThread ) ) * 100.0 ;
double percentDiff = percent - lastPercent ;
double toc = localTime . Toc ( ) ;
2014-10-15 11:19:59 -04:00
2014-07-08 03:11:14 -04:00
if ( percentDiff > = 10 | | ( toc > 1000 & & percentDiff > = 1 ) )
{
double etaMs = ( ( 100.0 - percent ) / percent ) * totalTime . Toc ( ) ;
2014-10-15 11:19:59 -04:00
2014-07-08 03:11:14 -04:00
if ( ! m_Callback - > ProgressFunc ( m_Ember , m_ProgressParameter , percent , 1 , etaMs ) )
Abort ( ) ;
2014-10-15 11:19:59 -04:00
2014-07-08 03:11:14 -04:00
lastPercent = percent ;
localTime . Tic ( ) ;
}
}
}
2017-08-28 23:45:58 -04:00
}
# if defined(_WIN32) || defined(__APPLE__)
, tbb : : static_partitioner ( )
# endif
) ;
2014-10-15 11:19:59 -04:00
2014-07-08 03:11:14 -04:00
if ( m_Callback & & ! m_Abort )
m_Callback - > ProgressFunc ( m_Ember , m_ProgressParameter , 100.0 , 1 , 0 ) ;
//totalTime.Toc(__FUNCTION__);
2015-12-31 19:00:36 -05:00
return m_Abort ? eRenderStatus : : RENDER_ABORT : eRenderStatus : : RENDER_OK ;
2014-07-08 03:11:14 -04:00
}
/// <summary>
2018-04-29 01:28:05 -04:00
/// Produce a final, visible image by clipping, gamma correcting and spatial filtering the color values
/// in the density filtering buffer and save to the passed in buffer.
2014-07-08 03:11:14 -04:00
/// </summary>
/// <param name="pixels">The pixel vector to allocate and store the final image in</param>
/// <param name="finalOffset">Offset in the buffer to store the pixels to</param>
/// <returns>True if not prematurely aborted, else false.</returns>
template < typename T , typename bucketT >
2017-07-22 16:43:35 -04:00
eRenderStatus Renderer < T , bucketT > : : AccumulatorToFinalImage ( vector < v4F > & pixels , size_t finalOffset )
2014-07-08 03:11:14 -04:00
{
2018-04-29 01:28:05 -04:00
EnterFinalAccum ( ) ;
2014-07-08 03:11:14 -04:00
2018-04-29 01:28:05 -04:00
if ( ! PrepFinalAccumVector ( pixels ) )
{
LeaveFinalAccum ( ) ;
2015-12-31 19:00:36 -05:00
return eRenderStatus : : RENDER_ERROR ;
2018-04-29 01:28:05 -04:00
}
2014-07-08 03:11:14 -04:00
//Timing t(4);
2014-10-14 11:53:15 -04:00
size_t filterWidth = m_SpatialFilter - > FinalFilterWidth ( ) ;
2015-08-10 23:10:23 -04:00
bucketT g , linRange , vibrancy ;
Color < bucketT > background ;
2018-04-29 01:28:05 -04:00
auto p = pixels . data ( ) ;
p + = finalOffset ;
2017-07-05 02:08:06 -04:00
PrepFinalAccumVals ( background , g , linRange , vibrancy ) ; //After this, background has been scaled from 0-1 to 0-255.
2014-07-08 03:11:14 -04:00
//If early clip, go through the entire accumulator and perform gamma correction first.
//The original does it this way as well and it's roughly 11 times faster to do it this way than inline below with each pixel.
if ( EarlyClip ( ) )
{
2017-07-05 02:08:06 -04:00
parallel_for ( size_t ( 0 ) , m_SuperRasH , size_t ( 1 ) , [ & ] ( size_t j )
2014-07-08 03:11:14 -04:00
{
2016-03-28 21:49:10 -04:00
auto rowStart = m_AccumulatorBuckets . data ( ) + ( j * m_SuperRasW ) ; //Pull out of inner loop for optimization.
auto rowEnd = rowStart + m_SuperRasW ;
2014-09-10 01:41:26 -04:00
2016-03-28 21:49:10 -04:00
while ( rowStart < rowEnd & & ! m_Abort ) //Use the pointer itself as the offset to save an extra addition per iter.
2014-07-08 03:11:14 -04:00
{
2017-07-22 16:43:35 -04:00
GammaCorrection ( * rowStart , background , g , linRange , vibrancy , false , glm : : value_ptr ( * rowStart ) ) ; //Write back in place.
2016-03-28 21:49:10 -04:00
rowStart + + ;
2014-07-08 03:11:14 -04:00
}
2017-08-28 23:45:58 -04:00
}
# if defined(_WIN32) || defined(__APPLE__)
, tbb : : static_partitioner ( )
# endif
) ;
2014-07-08 03:11:14 -04:00
}
if ( m_Abort )
{
LeaveFinalAccum ( ) ;
2015-12-31 19:00:36 -05:00
return eRenderStatus : : RENDER_ABORT ;
2014-07-08 03:11:14 -04:00
}
//Note that abort is not checked here. The final accumulation must run to completion
//otherwise artifacts that resemble page tearing will occur in an interactive run. It's
//critical to never exit this loop prematurely.
2014-10-14 11:53:15 -04:00
//for (size_t j = 0; j < FinalRasH(); j++)//Keep around for debugging.
--User changes
-Add a palette editor.
-Add support for reading .ugr/.gradient/.gradients palette files.
-Allow toggling on spinners whose minimum value is not zero.
-Allow toggling display of image, affines and grid.
-Add new variations: cylinder2, circlesplit, tile_log, truchet_fill, waves2_radial.
--Bug fixes
-cpow2 was wrong.
-Palettes with rapid changes in color would produce slightly different outputs from Apo/Chaotica. This was due to a long standing bug from flam3.
-Use exec() on Apple and show() on all other OSes for dialog boxes.
-Trying to render a sequence with no frames would crash.
-Selecting multiple xforms and rotating them would produce the wrong rotation.
-Better handling when parsing flames using different encoding, such as unicode and UTF-8.
-Switching between SP/DP didn't reselect the selected flame in the Library tab.
--Code changes
-Make all types concerning palettes be floats, including PaletteTableWidgetItem.
-PaletteTableWidgetItem is no longer templated because all palettes are float.
-Include the source colors for user created gradients.
-Change parallel_for() calls to work with very old versions of TBB which are lingering on some systems.
-Split conditional out of accumulation loop on the CPU for better performance.
-Vectorize summing when doing density filter for better performance.
-Make all usage of palettes be of type float, double is pointless.
-Allow palettes to reside in multiple folders, while ensuring only one of each name is added.
-Refactor some palette path searching code.
-Make ReadFile() throw and catch an exception if the file operation fails.
-A little extra safety in foci and foci3D with a call to Zeps().
-Cast to (real_t) in the OpenCL string for the w variation, which was having trouble compiling on Mac.
-Fixing missing comma between paths in InitPaletteList().
-Move Xml and PaletteList classes into cpp to shorten build times when working on them.
-Remove default param values for IterOpenCLKernelCreator<T>::SharedDataIndexDefines in cpp file.
-Change more NULL to nullptr.
2017-02-26 03:02:21 -05:00
parallel_for ( size_t ( 0 ) , FinalRasH ( ) , size_t ( 1 ) , [ & ] ( size_t j )
2014-07-08 03:11:14 -04:00
{
Color < bucketT > newBucket ;
2017-07-22 16:43:35 -04:00
size_t pixelsRowStart = ( m_YAxisUp ? ( ( FinalRasH ( ) - j ) - 1 ) : j ) * FinalRasW ( ) ; //Pull out of inner loop for optimization.
2014-10-14 11:53:15 -04:00
size_t y = m_DensityFilterOffset + ( j * Supersample ( ) ) ; //Start at the beginning row of each super sample block.
2016-03-28 21:49:10 -04:00
size_t clampedFilterH = std : : min ( filterWidth , m_SuperRasH - y ) ; //Make sure the filter doesn't go past the bottom of the gutter.
2018-04-29 01:28:05 -04:00
auto pv4T = p + pixelsRowStart ;
2014-07-08 03:11:14 -04:00
2017-07-22 16:43:35 -04:00
for ( size_t i = 0 ; i < FinalRasW ( ) ; i + + , pv4T + + )
2014-07-08 03:11:14 -04:00
{
2014-10-14 11:53:15 -04:00
size_t ii , jj ;
size_t x = m_DensityFilterOffset + ( i * Supersample ( ) ) ; //Start at the beginning column of each super sample block.
2016-03-28 21:49:10 -04:00
size_t clampedFilterW = std : : min ( filterWidth , m_SuperRasW - x ) ; //Make sure the filter doesn't go past the right of the gutter.
2014-07-08 03:11:14 -04:00
newBucket . Clear ( ) ;
2014-09-10 01:41:26 -04:00
2014-07-08 03:11:14 -04:00
//Original was iterating column-wise, which is slow.
//Here, iterate one row at a time, giving a 10% speed increase.
2016-03-28 21:49:10 -04:00
for ( jj = 0 ; jj < clampedFilterH ; jj + + )
2014-07-08 03:11:14 -04:00
{
2016-03-28 21:49:10 -04:00
size_t filterKRowIndex = jj * filterWidth ; //Use the full, non-clamped width to get the filter value.
2014-10-14 11:53:15 -04:00
size_t accumRowIndex = ( y + jj ) * m_SuperRasW ; //Pull out of inner loop for optimization.
2014-09-10 01:41:26 -04:00
2016-03-28 21:49:10 -04:00
for ( ii = 0 ; ii < clampedFilterW ; ii + + )
2014-07-08 03:11:14 -04:00
{
//Need to dereference the spatial filter pointer object to use the [] operator. Makes no speed difference.
2016-03-28 21:49:10 -04:00
bucketT k = ( ( * m_SpatialFilter ) [ filterKRowIndex + ii ] ) ;
newBucket + = ( m_AccumulatorBuckets [ accumRowIndex + ( x + ii ) ] * k ) ;
2014-07-08 03:11:14 -04:00
}
}
2014-09-10 01:41:26 -04:00
2017-07-22 16:43:35 -04:00
auto pf = reinterpret_cast < float * > ( pv4T ) ;
GammaCorrection ( * ( reinterpret_cast < tvec4 < bucketT , glm : : defaultp > * > ( & newBucket ) ) , background , g , linRange , vibrancy , true , pf ) ;
2014-07-08 03:11:14 -04:00
}
2017-08-28 23:45:58 -04:00
}
# if defined(_WIN32) || defined(__APPLE__)
, tbb : : static_partitioner ( )
# endif
) ;
2014-09-10 01:41:26 -04:00
2016-04-11 21:15:14 -04:00
//Insert the palette into the image for debugging purposes. Not implemented on the GPU.
if ( m_InsertPalette )
2014-07-08 03:11:14 -04:00
{
2014-10-14 11:53:15 -04:00
size_t i , j , ph = 100 ;
2014-07-08 03:11:14 -04:00
if ( ph > = FinalRasH ( ) )
ph = FinalRasH ( ) ;
2014-09-10 01:41:26 -04:00
2017-07-22 16:43:35 -04:00
for ( j = 0 ; j < ph ; j + + )
2016-04-11 21:15:14 -04:00
{
2017-07-22 16:43:35 -04:00
for ( i = 0 ; i < FinalRasW ( ) ; i + + )
2016-04-11 21:15:14 -04:00
{
2018-04-29 01:28:05 -04:00
auto pp = p + ( i + j * FinalRasW ( ) ) ;
pp - > r = m_TempEmber . m_Palette [ i * 256 / FinalRasW ( ) ] [ 0 ] ;
pp - > g = m_TempEmber . m_Palette [ i * 256 / FinalRasW ( ) ] [ 1 ] ;
pp - > b = m_TempEmber . m_Palette [ i * 256 / FinalRasW ( ) ] [ 2 ] ;
pp - > a = 1 ;
2014-07-08 03:11:14 -04:00
}
}
}
2015-12-31 19:00:36 -05:00
//t.Toc(__FUNCTION__);
2014-07-08 03:11:14 -04:00
LeaveFinalAccum ( ) ;
2015-12-31 19:00:36 -05:00
return m_Abort ? eRenderStatus : : RENDER_ABORT : eRenderStatus : : RENDER_OK ;
2014-07-08 03:11:14 -04:00
}
//#define TG 1
//#define NEWSUBBATCH 1
/// <summary>
/// Run the iteration algorithm for the specified number of iterations.
/// This is only called after all other setup has been done.
/// This function will be called multiple times for an interactive rendering, and
/// once for a straight through render.
/// The iteration is reset and fused in each thread after each sub batch is done
2014-11-28 04:37:51 -05:00
/// which by default is 10,240 iterations.
2014-07-08 03:11:14 -04:00
/// </summary>
/// <param name="iterCount">The number of iterations to run</param>
2014-11-03 02:16:34 -05:00
/// <param name="temporalSample">The temporal sample this is running for</param>
2014-07-08 03:11:14 -04:00
/// <returns>Rendering statistics</returns>
template < typename T , typename bucketT >
2014-11-03 02:16:34 -05:00
EmberStats Renderer < T , bucketT > : : Iterate ( size_t iterCount , size_t temporalSample )
2014-07-08 03:11:14 -04:00
{
//Timing t2(4);
2014-08-06 00:50:52 -04:00
m_IterTimer . Tic ( ) ;
2014-12-07 02:51:44 -05:00
size_t totalItersPerThread = size_t ( ceil ( double ( iterCount ) / double ( m_ThreadsToUse ) ) ) ;
2014-07-08 03:11:14 -04:00
double percent , etaMs ;
EmberStats stats ;
2016-12-05 22:04:33 -05:00
//vector<double> accumTimes(4);
2014-07-08 03:11:14 -04:00
--User changes
-Add new variations: bubbleT3D, crob, hexaplay3D, hexcrop, hexes, hexnix3D, loonie2, loonie3, nBlur, octapol and synth.
-Allow for pre/post versions of dc_bubble, dc_cylinder and dc_linear whereas before they were omitted.
-When saving a file with multiple embers in it, detect if time values are all the same and if so, start them at zero and increment by 1 for each ember.
-Allow for numerous quality increases to be coalesced into one. It will pick up at the end of the current render.
-Show selection highlight on variations tree in response to mouse hover. This makes it easier to see for which variation or param the current mouse wheel action will apply.
-Make default temporal samples be 100, whereas before it was 1000 which was overkill.
-Require the shift key to be held with delete for deleting an ember to prevent it from triggering when the user enters delete in the edit box.
-This wasn't otherwise fixable without writing a lot more code.
--Bug fixes
-EmberGenome was crashing when generating a sequence from a source file with more than 2 embers in it.
-EmberGenome was improperly handling the first frame of a merge after the last frame of the loop.
-These bugs were due to a previous commit. Revert parts of that commit.
-Prevent a zoom value of less than 0 when reading from xml.
-Slight optimization of the crescents, and mask variations, if the compiler wasn't doing it already.
-Unique file naming was broken because it was looking for _# and the default names ended with -#.
-Disallow renaming of an ember in the library tree to an empty string.
-Severe bug that prevented some variations from being read correctly from params generated outside this program.
-Severe OpenCL randomization bug. The first x coordinates of the first points in the first kernel call of the first ember of a render since the OpenCL renderer object was created were not random and were mostly -1.
-Severe bug when populating xform selection distributions that could sometimes cause a crash due to roundoff error. Fix by using double.
-Limit the max number of variations in a random ember to MAX_CL_VARS, which is 8. This ensures they'll look the same on CPU and GPU.
-Prevent user from saving stylesheet to default.qss, it's a special reserved filename.
--Code changes
-Generalize using the running sum output point inside of a variation for all cases: pre, reg and post.
-Allow for array variables in variations where the address of each element is stored in m_Params.
-Qualify all math functions with std::
-No longer use our own Clamp() in OpenCL, instead use the standard clamp().
-Redesign how functions are used in the variations OpenCL code.
-Add tests to EmberTester to verify some of the new functionality.
-Place more const and override qualifiers on functions where appropriate.
-Add a global rand with a lock to be used very sparingly.
-Use a map instead of a vector for bad param names in Xml parsing.
-Prefix affine interpolation mode defines with "AFFINE_" to make their purpose more clear.
-Allow for variations that change state during iteration by sending a separate copy of the ember to each rendering thread.
-Implement this same functionality with a local struct in OpenCL. It's members are the total of all variables that need to change state within an ember.
-Add Contains() function to Utils.h.
-EmberRender: print names of kernels being printed with --dump_kernel option.
-Clean up EmberTester to handle some of the recent changes.
-Fix various casts.
-Replace % 2 with & 1, even though the compiler was likely doing this already.
-Add new file Variations06.h to accommodate new variations.
-General cleanup.
2015-11-22 17:15:07 -05:00
//Do this every iteration for an animation, or else do it once for a single image. CPU only.
if ( ! m_LastIter )
{
m_ThreadEmbers . clear ( ) ;
m_ThreadEmbers . insert ( m_ThreadEmbers . begin ( ) , m_ThreadsToUse , m_Ember ) ;
}
2015-12-31 19:00:36 -05:00
--User changes
-Add a palette editor.
-Add support for reading .ugr/.gradient/.gradients palette files.
-Allow toggling on spinners whose minimum value is not zero.
-Allow toggling display of image, affines and grid.
-Add new variations: cylinder2, circlesplit, tile_log, truchet_fill, waves2_radial.
--Bug fixes
-cpow2 was wrong.
-Palettes with rapid changes in color would produce slightly different outputs from Apo/Chaotica. This was due to a long standing bug from flam3.
-Use exec() on Apple and show() on all other OSes for dialog boxes.
-Trying to render a sequence with no frames would crash.
-Selecting multiple xforms and rotating them would produce the wrong rotation.
-Better handling when parsing flames using different encoding, such as unicode and UTF-8.
-Switching between SP/DP didn't reselect the selected flame in the Library tab.
--Code changes
-Make all types concerning palettes be floats, including PaletteTableWidgetItem.
-PaletteTableWidgetItem is no longer templated because all palettes are float.
-Include the source colors for user created gradients.
-Change parallel_for() calls to work with very old versions of TBB which are lingering on some systems.
-Split conditional out of accumulation loop on the CPU for better performance.
-Vectorize summing when doing density filter for better performance.
-Make all usage of palettes be of type float, double is pointless.
-Allow palettes to reside in multiple folders, while ensuring only one of each name is added.
-Refactor some palette path searching code.
-Make ReadFile() throw and catch an exception if the file operation fails.
-A little extra safety in foci and foci3D with a call to Zeps().
-Cast to (real_t) in the OpenCL string for the w variation, which was having trouble compiling on Mac.
-Fixing missing comma between paths in InitPaletteList().
-Move Xml and PaletteList classes into cpp to shorten build times when working on them.
-Remove default param values for IterOpenCLKernelCreator<T>::SharedDataIndexDefines in cpp file.
-Change more NULL to nullptr.
2017-02-26 03:02:21 -05:00
parallel_for ( size_t ( 0 ) , m_ThreadsToUse , size_t ( 1 ) , [ & ] ( size_t threadIndex )
2014-07-08 03:11:14 -04:00
{
2016-03-01 20:26:45 -05:00
# if defined(_WIN32)
2016-12-05 22:04:33 -05:00
SetThreadPriority ( GetCurrentThread ( ) , int ( m_Priority ) ) ;
2015-06-22 10:03:15 -04:00
# elif defined(__APPLE__)
2016-12-05 22:04:33 -05:00
sched_param sp = { 0 } ;
--User changes
-Add a palette editor.
-Add support for reading .ugr/.gradient/.gradients palette files.
-Allow toggling on spinners whose minimum value is not zero.
-Allow toggling display of image, affines and grid.
-Add new variations: cylinder2, circlesplit, tile_log, truchet_fill, waves2_radial.
--Bug fixes
-cpow2 was wrong.
-Palettes with rapid changes in color would produce slightly different outputs from Apo/Chaotica. This was due to a long standing bug from flam3.
-Use exec() on Apple and show() on all other OSes for dialog boxes.
-Trying to render a sequence with no frames would crash.
-Selecting multiple xforms and rotating them would produce the wrong rotation.
-Better handling when parsing flames using different encoding, such as unicode and UTF-8.
-Switching between SP/DP didn't reselect the selected flame in the Library tab.
--Code changes
-Make all types concerning palettes be floats, including PaletteTableWidgetItem.
-PaletteTableWidgetItem is no longer templated because all palettes are float.
-Include the source colors for user created gradients.
-Change parallel_for() calls to work with very old versions of TBB which are lingering on some systems.
-Split conditional out of accumulation loop on the CPU for better performance.
-Vectorize summing when doing density filter for better performance.
-Make all usage of palettes be of type float, double is pointless.
-Allow palettes to reside in multiple folders, while ensuring only one of each name is added.
-Refactor some palette path searching code.
-Make ReadFile() throw and catch an exception if the file operation fails.
-A little extra safety in foci and foci3D with a call to Zeps().
-Cast to (real_t) in the OpenCL string for the w variation, which was having trouble compiling on Mac.
-Fixing missing comma between paths in InitPaletteList().
-Move Xml and PaletteList classes into cpp to shorten build times when working on them.
-Remove default param values for IterOpenCLKernelCreator<T>::SharedDataIndexDefines in cpp file.
-Change more NULL to nullptr.
2017-02-26 03:02:21 -05:00
sp . sched_priority = int ( m_Priority ) ;
2016-12-05 22:04:33 -05:00
pthread_setschedparam ( pthread_self ( ) , SCHED_RR , & sp ) ;
2015-06-17 23:05:53 -04:00
# else
2016-12-05 22:04:33 -05:00
pthread_setschedprio ( pthread_self ( ) , int ( m_Priority ) ) ;
2014-07-08 03:11:14 -04:00
# endif
2016-12-05 22:04:33 -05:00
//Timing t;
IterParams < T > params ;
m_BadVals [ threadIndex ] = 0 ;
params . m_Count = std : : min ( totalItersPerThread , SubBatchSize ( ) ) ;
params . m_Skip = FuseCount ( ) ;
//params.m_OneColDiv2 = m_CarToRas.OneCol() / 2;
//params.m_OneRowDiv2 = m_CarToRas.OneRow() / 2;
//Sub batch iterations, loop 2.
for ( m_SubBatch [ threadIndex ] = 0 ; ( m_SubBatch [ threadIndex ] < totalItersPerThread ) & & ! m_Abort ; m_SubBatch [ threadIndex ] + = params . m_Count )
{
//Must recalculate the number of iters to run on each sub batch because the last batch will most likely have less than SubBatchSize iters.
//For example, if 51,000 are requested, and the sbs is 10,000, it should run 5 sub batches of 10,000 iters, and one final sub batch of 1,000 iters.
params . m_Count = std : : min ( params . m_Count , totalItersPerThread - m_SubBatch [ threadIndex ] ) ;
//Use first as random point, the rest are iterated points.
//Note that this gets reset with a new random point for each subBatchSize iterations.
//This helps correct if iteration happens to be on a bad trajectory.
m_Samples [ threadIndex ] [ 0 ] . m_X = m_Rand [ threadIndex ] . template Frand11 < T > ( ) ;
m_Samples [ threadIndex ] [ 0 ] . m_Y = m_Rand [ threadIndex ] . template Frand11 < T > ( ) ;
m_Samples [ threadIndex ] [ 0 ] . m_Z = 0 ; //m_Ember.m_CamZPos;//Apo set this to 0, then made the user use special variations to kick it. It seems easier to just set it to zpos.
m_Samples [ threadIndex ] [ 0 ] . m_ColorX = m_Rand [ threadIndex ] . template Frand01 < T > ( ) ;
2018-03-30 12:56:24 -04:00
//Check if the user wanted to suspend the process.
while ( Paused ( ) )
std : : this_thread : : sleep_for ( 500 ms ) ;
2016-12-05 22:04:33 -05:00
//Finally, iterate.
//t.Tic();
//Iterating, loop 3.
m_BadVals [ threadIndex ] + = m_Iterator - > Iterate ( m_ThreadEmbers [ threadIndex ] , params , m_Samples [ threadIndex ] . data ( ) , m_Rand [ threadIndex ] ) ;
//iterationTime += t.Toc();
if ( m_LockAccum )
m_AccumCs . lock ( ) ;
//t.Tic();
//Map temp buffer samples into the histogram using the palette for color.
Accumulate ( m_Rand [ threadIndex ] , m_Samples [ threadIndex ] . data ( ) , params . m_Count , & m_Dmap ) ;
//accumTimes[threadIndex] += t.Toc();
if ( m_LockAccum )
m_AccumCs . unlock ( ) ;
if ( m_Callback & & threadIndex = = 0 )
2014-07-08 03:11:14 -04:00
{
2016-12-05 22:04:33 -05:00
percent = 100.0 *
double
(
2015-12-31 19:00:36 -05:00
double
(
double
(
2016-12-05 22:04:33 -05:00
//Takes progress of current thread and multiplies by thread count.
//This assumes the threads progress at roughly the same speed.
double ( m_LastIter + ( m_SubBatch [ threadIndex ] * m_ThreadsToUse ) ) / double ( ItersPerTemporalSample ( ) )
) + temporalSample
) / double ( TemporalSamples ( ) )
) ;
double percentDiff = percent - m_LastIterPercent ;
double toc = m_ProgressTimer . Toc ( ) ;
if ( percentDiff > = 10 | | ( toc > 1000 & & percentDiff > = 1 ) ) //Call callback function if either 10% has passed, or one second (and 1%).
{
etaMs = ( ( 100.0 - percent ) / percent ) * m_RenderTimer . Toc ( ) ;
2014-09-10 01:41:26 -04:00
2016-12-05 22:04:33 -05:00
if ( ! m_Callback - > ProgressFunc ( m_Ember , m_ProgressParameter , percent , 0 , etaMs ) )
Abort ( ) ;
2014-07-08 03:11:14 -04:00
2016-12-05 22:04:33 -05:00
m_LastIterPercent = percent ;
m_ProgressTimer . Tic ( ) ;
2014-07-08 03:11:14 -04:00
}
}
2016-12-05 22:04:33 -05:00
}
2017-08-28 23:45:58 -04:00
}
# if defined(_WIN32) || defined(__APPLE__)
, tbb : : static_partitioner ( )
# endif
) ;
2014-07-08 03:11:14 -04:00
stats . m_Iters = std : : accumulate ( m_SubBatch . begin ( ) , m_SubBatch . end ( ) , 0ULL ) ; //Sum of iter count of all threads.
2014-08-06 00:50:52 -04:00
stats . m_Badvals = std : : accumulate ( m_BadVals . begin ( ) , m_BadVals . end ( ) , 0ULL ) ;
stats . m_IterMs = m_IterTimer . Toc ( ) ;
2016-12-05 22:04:33 -05:00
//cout << "Accum time: " << std::accumulate(accumTimes.begin(), accumTimes.end(), 0.0) << endl;
2014-07-08 03:11:14 -04:00
//t2.Toc(__FUNCTION__);
return stats ;
}
/// <summary>
2014-10-14 11:53:15 -04:00
/// Non-virtual render properties, getters and setters.
2014-07-26 15:03:51 -04:00
/// </summary>
2014-07-08 03:11:14 -04:00
/// <summary>
2014-10-14 11:53:15 -04:00
/// Get the pixel aspect ratio of the output image.
2014-07-08 03:11:14 -04:00
/// Default: 1.
/// </summary>
2014-10-14 11:53:15 -04:00
/// <returns>The pixel aspect ratio.</returns>
template < typename T , typename bucketT > T Renderer < T , bucketT > : : PixelAspectRatio ( ) const { return m_PixelAspectRatio ; }
2014-07-08 03:11:14 -04:00
/// <summary>
2014-10-14 11:53:15 -04:00
/// Set the pixel aspect ratio of the output image.
/// Reset the rendering process.
2014-07-08 03:11:14 -04:00
/// </summary>
2014-10-14 11:53:15 -04:00
/// <param name="pixelAspectRatio">The pixel aspect ratio.</param>
2014-07-08 03:11:14 -04:00
template < typename T , typename bucketT >
2014-10-14 11:53:15 -04:00
void Renderer < T , bucketT > : : PixelAspectRatio ( T pixelAspectRatio )
2014-07-08 03:11:14 -04:00
{
2015-12-31 19:00:36 -05:00
ChangeVal ( [ & ] { m_PixelAspectRatio = pixelAspectRatio ; } , eProcessAction : : FULL_RENDER ) ;
2014-07-08 03:11:14 -04:00
}
/// <summary>
2014-10-14 11:53:15 -04:00
/// Non-virtual renderer properties, getters only.
2014-07-08 03:11:14 -04:00
/// </summary>
2015-03-21 18:27:37 -04:00
template < typename T , typename bucketT > T Renderer < T , bucketT > : : Scale ( ) const { return m_Scale ; }
template < typename T , typename bucketT > T Renderer < T , bucketT > : : PixelsPerUnitX ( ) const { return m_PixelsPerUnitX ; }
template < typename T , typename bucketT > T Renderer < T , bucketT > : : PixelsPerUnitY ( ) const { return m_PixelsPerUnitY ; }
2015-08-10 23:10:23 -04:00
template < typename T , typename bucketT > bucketT Renderer < T , bucketT > : : K1 ( ) const { return m_K1 ; }
template < typename T , typename bucketT > bucketT Renderer < T , bucketT > : : K2 ( ) const { return m_K2 ; }
--User changes
-Add support for multiple GPU devices.
--These options are present in the command line and in Fractorium.
-Change scheme of specifying devices from platform,device to just total device index.
--Single number on the command line.
--Change from combo boxes for device selection to a table of all devices in Fractorium.
-Temporal samples defaults to 100 instead of 1000 which was needless overkill.
--Bug fixes
-EmberAnimate, EmberRender, FractoriumSettings, FinalRenderDialog: Fix wrong order of arguments to Clamp() when assigning thread priority.
-VariationsDC.h: Fix NVidia OpenCL compilation error in DCTriangleVariation.
-FractoriumXformsColor.cpp: Checking for null pixmap pointer is not enough, must also check if the underlying buffer is null via call to QPixmap::isNull().
--Code changes
-Ember.h: Add case for FLAME_MOTION_NONE and default in ApplyFlameMotion().
-EmberMotion.h: Call base constructor.
-EmberPch.h: #pragma once only on Windows.
-EmberToXml.h:
--Handle different types of exceptions.
--Add default cases to ToString().
-Isaac.h: Remove unused variable in constructor.
-Point.h: Call base constructor in Color().
-Renderer.h/cpp:
--Add bool to Alloc() to only allocate memory for the histogram. Needed for multi-GPU.
--Make CoordMap() return a const ref, not a pointer.
-SheepTools.h:
--Use 64-bit types like the rest of the code already does.
--Fix some comment misspellings.
-Timing.h: Make BeginTime(), EndTime(), ElapsedTime() and Format() be const functions.
-Utils.h:
--Add new functions Equal() and Split().
--Handle more exception types in ReadFile().
--Get rid of most legacy blending of C and C++ argument parsing.
-XmlToEmber.h:
--Get rid of most legacy blending of C and C++ code from flam3.
--Remove some unused variables.
-EmberAnimate:
--Support multi-GPU processing that alternates full frames between devices.
--Use OpenCLInfo instead of OpenCLWrapper for --openclinfo option.
--Remove bucketT template parameter, and hard code float in its place.
--If a render fails, exit since there is no point in continuing an animation with a missing frame.
--Pass variables to threaded save better, which most likely fixes a very subtle bug that existed before.
--Remove some unused variables.
-EmberGenome, EmberRender:
--Support multi-GPU processing that alternates full frames between devices.
--Use OpenCLInfo instead of OpenCLWrapper for --openclinfo option.
--Remove bucketT template parameter, and hard code float in its place.
-EmberRender:
--Support multi-GPU processing that alternates full frames between devices.
--Use OpenCLInfo instead of OpenCLWrapper for --openclinfo option.
--Remove bucketT template parameter, and hard code float in its place.
--Only print values when not rendering with OpenCL, since they're always 0 in that case.
-EmberCLPch.h:
--#pragma once only on Windows.
--#include <atomic>.
-IterOpenCLKernelCreator.h: Add new kernel for summing two histograms. This is needed for multi-GPU.
-OpenCLWrapper.h:
--Move all OpenCL info related code into its own class OpenCLInfo.
--Add members to cache the values of global memory size and max allocation size.
-RendererCL.h/cpp:
--Redesign to accomodate multi-GPU.
--Constructor now takes a vector of devices.
--Remove DumpErrorReport() function, it's handled in the base.
--ClearBuffer(), ReadPoints(), WritePoints(), ReadHist() and WriteHist() now optionally take a device index as a parameter.
--MakeDmap() override and m_DmapCL member removed because it no longer applies since the histogram is always float since the last commit.
--Add new function SumDeviceHist() to sum histograms from two devices by first copying to a temporary on the host, then a temporary on the device, then summing.
--m_Calls member removed, as it's now per-device.
--OpenCLWrapper removed.
--m_Seeds member is now a vector of vector of seeds, to accomodate a separate and different array of seeds for each device.
--Added member m_Devices, a vector of unique_ptr of RendererCLDevice.
-EmberCommon.h
--Added Devices() function to convert from a vector of device indices to a vector of platform,device indices.
--Changed CreateRenderer() to accept a vector of devices to create a single RendererCL which will split work across multiple devices.
--Added CreateRenderers() function to accept a vector of devices to create multiple RendererCL, each which will render on a single device.
--Add more comments to some existing functions.
-EmberCommonPch.h: #pragma once only on Windows.
-EmberOptions.h:
--Remove --platform option, it's just sequential device number now with the --device option.
--Make --out be OPT_USE_RENDER instead of OPT_RENDER_ANIM since it's an error condition when animating. It makes no sense to write all frames to a single image.
--Add Devices() function to parse comma separated --device option string and return a vector of device indices.
--Make int and uint types be 64-bit, so intmax_t and size_t.
--Make better use of macros.
-JpegUtils.h: Make string parameters to WriteJpeg() and WritePng() be const ref.
-All project files: Turn off buffer security check option in Visual Studio (/Gs-)
-deployment.pri: Remove the line OTHER_FILES +=, it's pointless and was causing problems.
-Ember.pro, EmberCL.pro: Add CONFIG += plugin, otherwise it wouldn't link.
-EmberCL.pro: Add new files for multi-GPU support.
-build_all.sh: use -j4 and QMAKE=${QMAKE:/usr/bin/qmake}
-shared_settings.pri:
-Add version string.
-Remove old DESTDIR definitions.
-Add the following lines or else nothing would build:
CONFIG(release, debug|release) {
CONFIG += warn_off
DESTDIR = ../../../Bin/release
}
CONFIG(debug, debug|release) {
DESTDIR = ../../../Bin/debug
}
QMAKE_POST_LINK += $$quote(cp --update ../../../Data/flam3-palettes.xml $${DESTDIR}$$escape_expand(\n\t))
LIBS += -L/usr/lib -lpthread
-AboutDialog.ui: Another futile attempt to make it look correct on Linux.
-FinalRenderDialog.h/cpp:
--Add support for multi-GPU.
--Change from combo boxes for device selection to a table of all devices.
--Ensure device selection makes sense.
--Remove "FinalRender" prefix of various function names, it's implied given the context.
-FinalRenderEmberController.h/cpp:
--Add support for multi-GPU.
--Change m_FinishedImageCount to be atomic.
--Move CancelRender() from the base to FinalRenderEmberController<T>.
--Refactor RenderComplete() to omit any progress related functionality or image saving since it can be potentially ran in a thread.
--Consolidate setting various renderer fields into SyncGuiToRenderer().
-Fractorium.cpp: Allow for resizing of the options dialog to show the entire device table.
-FractoriumCommon.h: Add various functions to handle a table showing the available OpenCL devices on the system.
-FractoriumEmberController.h/cpp: Remove m_FinalImageIndex, it's no longer needed.
-FractoriumRender.cpp: Scale the interactive sub batch count and quality by the number of devices used.
-FractoriumSettings.h/cpp:
--Temporal samples defaults to 100 instead of 1000 which was needless overkill.
--Add multi-GPU support, remove old device,platform pair.
-FractoriumToolbar.cpp: Disable OpenCL toolbar button if there are no devices present on the system.
-FractoriumOptionsDialog.h/cpp:
--Add support for multi-GPU.
--Consolidate more assignments in DataToGui().
--Enable/disable CPU/OpenCL items in response to OpenCL checkbox event.
-Misc: Convert almost everything to size_t for unsigned, intmax_t for signed.
2015-09-12 21:33:45 -04:00
template < typename T , typename bucketT > const CarToRas < T > & Renderer < T , bucketT > : : CoordMap ( ) const { return m_CarToRas ; }
2015-03-21 18:27:37 -04:00
template < typename T , typename bucketT > tvec4 < bucketT , glm : : defaultp > * Renderer < T , bucketT > : : HistBuckets ( ) { return m_HistBuckets . data ( ) ; }
template < typename T , typename bucketT > tvec4 < bucketT , glm : : defaultp > * Renderer < T , bucketT > : : AccumulatorBuckets ( ) { return m_AccumulatorBuckets . data ( ) ; }
2015-08-10 23:10:23 -04:00
template < typename T , typename bucketT > SpatialFilter < bucketT > * Renderer < T , bucketT > : : GetSpatialFilter ( ) { return m_SpatialFilter . get ( ) ; }
2015-03-21 18:27:37 -04:00
template < typename T , typename bucketT > TemporalFilter < T > * Renderer < T , bucketT > : : GetTemporalFilter ( ) { return m_TemporalFilter . get ( ) ; }
2014-07-08 03:11:14 -04:00
/// <summary>
2014-10-14 11:53:15 -04:00
/// Virtual renderer properties overridden from RendererBase, getters only.
2014-07-08 03:11:14 -04:00
/// </summary>
2014-12-07 02:51:44 -05:00
template < typename T , typename bucketT > double Renderer < T , bucketT > : : ScaledQuality ( ) const { return double ( m_ScaledQuality ) ; }
template < typename T , typename bucketT > double Renderer < T , bucketT > : : LowerLeftX ( bool gutter ) const { return double ( gutter ? m_CarToRas . CarLlX ( ) : m_LowerLeftX ) ; }
template < typename T , typename bucketT > double Renderer < T , bucketT > : : LowerLeftY ( bool gutter ) const { return double ( gutter ? m_CarToRas . CarLlY ( ) : m_LowerLeftY ) ; }
template < typename T , typename bucketT > double Renderer < T , bucketT > : : UpperRightX ( bool gutter ) const { return double ( gutter ? m_CarToRas . CarUrX ( ) : m_UpperRightX ) ; }
template < typename T , typename bucketT > double Renderer < T , bucketT > : : UpperRightY ( bool gutter ) const { return double ( gutter ? m_CarToRas . CarUrY ( ) : m_UpperRightY ) ; }
2014-10-14 11:53:15 -04:00
template < typename T , typename bucketT > DensityFilterBase * Renderer < T , bucketT > : : GetDensityFilter ( ) { return m_DensityFilter . get ( ) ; }
2014-07-08 03:11:14 -04:00
/// <summary>
2014-10-14 11:53:15 -04:00
/// Non-virtual ember wrappers, getters only.
2014-07-08 03:11:14 -04:00
/// </summary>
--User changes
-Add a palette editor.
-Add support for reading .ugr/.gradient/.gradients palette files.
-Allow toggling on spinners whose minimum value is not zero.
-Allow toggling display of image, affines and grid.
-Add new variations: cylinder2, circlesplit, tile_log, truchet_fill, waves2_radial.
--Bug fixes
-cpow2 was wrong.
-Palettes with rapid changes in color would produce slightly different outputs from Apo/Chaotica. This was due to a long standing bug from flam3.
-Use exec() on Apple and show() on all other OSes for dialog boxes.
-Trying to render a sequence with no frames would crash.
-Selecting multiple xforms and rotating them would produce the wrong rotation.
-Better handling when parsing flames using different encoding, such as unicode and UTF-8.
-Switching between SP/DP didn't reselect the selected flame in the Library tab.
--Code changes
-Make all types concerning palettes be floats, including PaletteTableWidgetItem.
-PaletteTableWidgetItem is no longer templated because all palettes are float.
-Include the source colors for user created gradients.
-Change parallel_for() calls to work with very old versions of TBB which are lingering on some systems.
-Split conditional out of accumulation loop on the CPU for better performance.
-Vectorize summing when doing density filter for better performance.
-Make all usage of palettes be of type float, double is pointless.
-Allow palettes to reside in multiple folders, while ensuring only one of each name is added.
-Refactor some palette path searching code.
-Make ReadFile() throw and catch an exception if the file operation fails.
-A little extra safety in foci and foci3D with a call to Zeps().
-Cast to (real_t) in the OpenCL string for the w variation, which was having trouble compiling on Mac.
-Fixing missing comma between paths in InitPaletteList().
-Move Xml and PaletteList classes into cpp to shorten build times when working on them.
-Remove default param values for IterOpenCLKernelCreator<T>::SharedDataIndexDefines in cpp file.
-Change more NULL to nullptr.
2017-02-26 03:02:21 -05:00
template < typename T , typename bucketT > bool Renderer < T , bucketT > : : XaosPresent ( ) const { return m_Ember . XaosPresent ( ) ; }
template < typename T , typename bucketT > size_t Renderer < T , bucketT > : : Supersample ( ) const { return m_Ember . m_Supersample ; }
template < typename T , typename bucketT > size_t Renderer < T , bucketT > : : PaletteIndex ( ) const { return m_Ember . PaletteIndex ( ) ; }
template < typename T , typename bucketT > T Renderer < T , bucketT > : : Time ( ) const { return m_Ember . m_Time ; }
template < typename T , typename bucketT > T Renderer < T , bucketT > : : Quality ( ) const { return m_Ember . m_Quality ; }
template < typename T , typename bucketT > T Renderer < T , bucketT > : : SpatialFilterRadius ( ) const { return m_Ember . m_SpatialFilterRadius ; }
template < typename T , typename bucketT > T Renderer < T , bucketT > : : PixelsPerUnit ( ) const { return m_Ember . m_PixelsPerUnit ; }
template < typename T , typename bucketT > T Renderer < T , bucketT > : : Zoom ( ) const { return m_Ember . m_Zoom ; }
template < typename T , typename bucketT > T Renderer < T , bucketT > : : CenterX ( ) const { return m_Ember . m_CenterX ; }
template < typename T , typename bucketT > T Renderer < T , bucketT > : : CenterY ( ) const { return m_Ember . m_CenterY ; }
template < typename T , typename bucketT > T Renderer < T , bucketT > : : Rotate ( ) const { return m_Ember . m_Rotate ; }
template < typename T , typename bucketT > bucketT Renderer < T , bucketT > : : Brightness ( ) const { return bucketT ( m_Ember . m_Brightness ) ; }
template < typename T , typename bucketT > bucketT Renderer < T , bucketT > : : Gamma ( ) const { return bucketT ( m_Ember . m_Gamma ) ; }
template < typename T , typename bucketT > bucketT Renderer < T , bucketT > : : Vibrancy ( ) const { return bucketT ( m_Ember . m_Vibrancy ) ; }
template < typename T , typename bucketT > bucketT Renderer < T , bucketT > : : GammaThresh ( ) const { return bucketT ( m_Ember . m_GammaThresh ) ; }
template < typename T , typename bucketT > bucketT Renderer < T , bucketT > : : HighlightPower ( ) const { return bucketT ( m_Ember . m_HighlightPower ) ; }
template < typename T , typename bucketT > Color < T > Renderer < T , bucketT > : : Background ( ) const { return m_Ember . m_Background ; }
template < typename T , typename bucketT > const Xform < T > * Renderer < T , bucketT > : : Xforms ( ) const { return m_Ember . Xforms ( ) ; }
template < typename T , typename bucketT > Xform < T > * Renderer < T , bucketT > : : NonConstXforms ( ) { return m_Ember . NonConstXforms ( ) ; }
template < typename T , typename bucketT > size_t Renderer < T , bucketT > : : XformCount ( ) const { return m_Ember . XformCount ( ) ; }
template < typename T , typename bucketT > const Xform < T > * Renderer < T , bucketT > : : FinalXform ( ) const { return m_Ember . FinalXform ( ) ; }
template < typename T , typename bucketT > Xform < T > * Renderer < T , bucketT > : : NonConstFinalXform ( ) { return m_Ember . NonConstFinalXform ( ) ; }
template < typename T , typename bucketT > bool Renderer < T , bucketT > : : UseFinalXform ( ) const { return m_Ember . UseFinalXform ( ) ; }
template < typename T , typename bucketT > const Palette < float > * Renderer < T , bucketT > : : GetPalette ( ) const { return & m_Ember . m_Palette ; }
template < typename T , typename bucketT > ePaletteMode Renderer < T , bucketT > : : PaletteMode ( ) const { return m_Ember . m_PaletteMode ; }
2014-07-08 03:11:14 -04:00
/// <summary>
2014-10-14 11:53:15 -04:00
/// Virtual ember wrappers overridden from RendererBase, getters only.
2014-07-08 03:11:14 -04:00
/// </summary>
2014-10-14 11:53:15 -04:00
template < typename T , typename bucketT > size_t Renderer < T , bucketT > : : TemporalSamples ( ) const { return m_Ember . m_TemporalSamples ; }
template < typename T , typename bucketT > size_t Renderer < T , bucketT > : : FinalRasW ( ) const { return m_Ember . m_FinalRasW ; }
template < typename T , typename bucketT > size_t Renderer < T , bucketT > : : FinalRasH ( ) const { return m_Ember . m_FinalRasH ; }
2014-11-28 04:37:51 -05:00
template < typename T , typename bucketT > size_t Renderer < T , bucketT > : : SubBatchSize ( ) const { return m_Ember . m_SubBatchSize ; }
template < typename T , typename bucketT > size_t Renderer < T , bucketT > : : FuseCount ( ) const { return m_Ember . m_FuseCount ; }
2014-07-08 03:11:14 -04:00
/// <summary>
2014-10-14 11:53:15 -04:00
/// Non-virtual iterator wrappers.
2014-07-08 03:11:14 -04:00
/// </summary>
2015-10-27 00:31:35 -04:00
template < typename T , typename bucketT > const byte * Renderer < T , bucketT > : : XformDistributions ( ) const { return m_Iterator ? m_Iterator - > XformDistributions ( ) : nullptr ; }
template < typename T , typename bucketT > size_t Renderer < T , bucketT > : : XformDistributionsSize ( ) const { return m_Iterator ? m_Iterator - > XformDistributionsSize ( ) : 0 ; }
2014-12-07 02:51:44 -05:00
template < typename T , typename bucketT > Point < T > * Renderer < T , bucketT > : : Samples ( size_t threadIndex ) const { return threadIndex < m_Samples . size ( ) ? const_cast < Point < T > * > ( m_Samples [ threadIndex ] . data ( ) ) : nullptr ; }
2014-07-08 03:11:14 -04:00
/// <summary>
/// Non-virtual functions that might be needed by a derived class.
/// </summary>
/// <summary>
/// Prepare various values needed for producing a final output image.
/// </summary>
/// <param name="background">The computed background value, which may differ from the background member</param>
/// <param name="g">The computed gamma</param>
/// <param name="linRange">The computed linear range</param>
/// <param name="vibrancy">The computed vibrancy</param>
template < typename T , typename bucketT >
2015-08-10 23:10:23 -04:00
void Renderer < T , bucketT > : : PrepFinalAccumVals ( Color < bucketT > & background , bucketT & g , bucketT & linRange , bucketT & vibrancy )
2014-07-08 03:11:14 -04:00
{
//If they are doing incremental rendering, they can get here without doing a full temporal
//sample, which means the values will be zero.
2015-08-10 23:10:23 -04:00
vibrancy = m_Vibrancy = = 0 ? Vibrancy ( ) : m_Vibrancy ;
2014-10-14 11:53:15 -04:00
size_t vibGamCount = m_VibGamCount = = 0 ? 1 : m_VibGamCount ;
2015-08-10 23:10:23 -04:00
bucketT gamma = m_Gamma = = 0 ? Gamma ( ) : m_Gamma ;
g = 1 / ClampGte < bucketT > ( gamma / vibGamCount , bucketT ( 0.01 ) ) ; //Ensure a divide by zero doesn't occur.
2014-07-08 03:11:14 -04:00
linRange = GammaThresh ( ) ;
vibrancy / = vibGamCount ;
2017-07-05 02:08:06 -04:00
background . x = ( IsNearZero ( m_Background . r ) ? bucketT ( m_Ember . m_Background . r ) : m_Background . r ) / vibGamCount ;
background . y = ( IsNearZero ( m_Background . g ) ? bucketT ( m_Ember . m_Background . g ) : m_Background . g ) / vibGamCount ;
background . z = ( IsNearZero ( m_Background . b ) ? bucketT ( m_Ember . m_Background . b ) : m_Background . b ) / vibGamCount ;
2014-07-08 03:11:14 -04:00
}
/// <summary>
2014-10-14 11:53:15 -04:00
/// Miscellaneous non-virtual functions used only in this class.
2014-07-08 03:11:14 -04:00
/// </summary>
/// <summary>
/// Accumulate the samples to the histogram.
/// To be called after a sub batch is finished iterating.
/// </summary>
/// <param name="samples">The samples to accumulate</param>
/// <param name="sampleCount">The number of samples</param>
/// <param name="palette">The palette to use</param>
template < typename T , typename bucketT >
2014-11-28 04:37:51 -05:00
void Renderer < T , bucketT > : : Accumulate ( QTIsaac < ISAAC_SIZE , ISAAC_INT > & rand , Point < T > * samples , size_t sampleCount , const Palette < bucketT > * palette )
2014-07-08 03:11:14 -04:00
{
2014-10-14 11:53:15 -04:00
size_t histIndex , intColorIndex , histSize = m_HistBuckets . size ( ) ;
2014-07-08 03:11:14 -04:00
bucketT colorIndex , colorIndexFrac ;
2014-11-28 04:37:51 -05:00
--User changes
-Add a palette editor.
-Add support for reading .ugr/.gradient/.gradients palette files.
-Allow toggling on spinners whose minimum value is not zero.
-Allow toggling display of image, affines and grid.
-Add new variations: cylinder2, circlesplit, tile_log, truchet_fill, waves2_radial.
--Bug fixes
-cpow2 was wrong.
-Palettes with rapid changes in color would produce slightly different outputs from Apo/Chaotica. This was due to a long standing bug from flam3.
-Use exec() on Apple and show() on all other OSes for dialog boxes.
-Trying to render a sequence with no frames would crash.
-Selecting multiple xforms and rotating them would produce the wrong rotation.
-Better handling when parsing flames using different encoding, such as unicode and UTF-8.
-Switching between SP/DP didn't reselect the selected flame in the Library tab.
--Code changes
-Make all types concerning palettes be floats, including PaletteTableWidgetItem.
-PaletteTableWidgetItem is no longer templated because all palettes are float.
-Include the source colors for user created gradients.
-Change parallel_for() calls to work with very old versions of TBB which are lingering on some systems.
-Split conditional out of accumulation loop on the CPU for better performance.
-Vectorize summing when doing density filter for better performance.
-Make all usage of palettes be of type float, double is pointless.
-Allow palettes to reside in multiple folders, while ensuring only one of each name is added.
-Refactor some palette path searching code.
-Make ReadFile() throw and catch an exception if the file operation fails.
-A little extra safety in foci and foci3D with a call to Zeps().
-Cast to (real_t) in the OpenCL string for the w variation, which was having trouble compiling on Mac.
-Fixing missing comma between paths in InitPaletteList().
-Move Xml and PaletteList classes into cpp to shorten build times when working on them.
-Remove default param values for IterOpenCLKernelCreator<T>::SharedDataIndexDefines in cpp file.
-Change more NULL to nullptr.
2017-02-26 03:02:21 -05:00
//Linear is a linear scale for when the color index is not a whole number, which is most of the time.
//It uses a portion of the value of the index, and the remainder of the next index.
//Example: index = 25.7
//Fraction = 0.7
//Color = (dmap[25] * 0.3) + (dmap[26] * 0.7)
//Use overloaded addition and multiplication operators in vec4 to perform the accumulation.
if ( PaletteMode ( ) = = ePaletteMode : : PALETTE_LINEAR )
{
//It's critical to understand what's going on here as it's one of the most important parts of the algorithm.
//A color value gets retrieved from the palette and
//its RGB values are added to the existing RGB values in the histogram bucket.
//Alpha is always 1 in the palettes, so that serves as the hit count.
//This differs from the original since redundantly adding both an alpha component and a hit count is omitted.
//This will eventually leave us with large values for pixels with many hits, which will be log scaled down later.
//Original used a function called bump_no_overflow(). Just do a straight add because the type will always be float or double.
//Doing so gives a 25% speed increase.
//Splitting these conditionals into separate loops makes no speed difference.
for ( size_t i = 0 ; i < sampleCount & & ! m_Abort ; i + + )
2014-07-08 03:11:14 -04:00
{
--User changes
-Add a palette editor.
-Add support for reading .ugr/.gradient/.gradients palette files.
-Allow toggling on spinners whose minimum value is not zero.
-Allow toggling display of image, affines and grid.
-Add new variations: cylinder2, circlesplit, tile_log, truchet_fill, waves2_radial.
--Bug fixes
-cpow2 was wrong.
-Palettes with rapid changes in color would produce slightly different outputs from Apo/Chaotica. This was due to a long standing bug from flam3.
-Use exec() on Apple and show() on all other OSes for dialog boxes.
-Trying to render a sequence with no frames would crash.
-Selecting multiple xforms and rotating them would produce the wrong rotation.
-Better handling when parsing flames using different encoding, such as unicode and UTF-8.
-Switching between SP/DP didn't reselect the selected flame in the Library tab.
--Code changes
-Make all types concerning palettes be floats, including PaletteTableWidgetItem.
-PaletteTableWidgetItem is no longer templated because all palettes are float.
-Include the source colors for user created gradients.
-Change parallel_for() calls to work with very old versions of TBB which are lingering on some systems.
-Split conditional out of accumulation loop on the CPU for better performance.
-Vectorize summing when doing density filter for better performance.
-Make all usage of palettes be of type float, double is pointless.
-Allow palettes to reside in multiple folders, while ensuring only one of each name is added.
-Refactor some palette path searching code.
-Make ReadFile() throw and catch an exception if the file operation fails.
-A little extra safety in foci and foci3D with a call to Zeps().
-Cast to (real_t) in the OpenCL string for the w variation, which was having trouble compiling on Mac.
-Fixing missing comma between paths in InitPaletteList().
-Move Xml and PaletteList classes into cpp to shorten build times when working on them.
-Remove default param values for IterOpenCLKernelCreator<T>::SharedDataIndexDefines in cpp file.
-Change more NULL to nullptr.
2017-02-26 03:02:21 -05:00
Point < T > p ( samples [ i ] ) ; //Slightly faster to cache this.
2014-07-08 03:11:14 -04:00
2017-03-27 21:05:06 -04:00
if ( p . m_Opacity ! = 0 )
2014-07-08 03:11:14 -04:00
{
2017-03-27 21:05:06 -04:00
if ( Rotate ( ) ! = 0 )
{
T p00 = p . m_X - CenterX ( ) ;
T p11 = p . m_Y - m_Ember . m_RotCenterY ;
p . m_X = ( p00 * m_RotMat . A ( ) ) + ( p11 * m_RotMat . B ( ) ) + CenterX ( ) ;
p . m_Y = ( p00 * m_RotMat . D ( ) ) + ( p11 * m_RotMat . E ( ) ) + m_Ember . m_RotCenterY ;
}
2014-09-10 01:41:26 -04:00
2017-03-27 21:05:06 -04:00
//Checking this first before converting gives better performance than converting and checking a single value, which the original did.
//Second, an interesting optimization observation is that when keeping the bounds vars within m_CarToRas and calling its InBounds() member function,
//rather than here as members, about a 7% speedup is achieved. This is possibly due to the fact that data from m_CarToRas is accessed
//right after the call to Convert(), so some caching efficiencies get realized.
if ( m_CarToRas . InBounds ( p ) )
2014-07-08 03:11:14 -04:00
{
--User changes
-Add a palette editor.
-Add support for reading .ugr/.gradient/.gradients palette files.
-Allow toggling on spinners whose minimum value is not zero.
-Allow toggling display of image, affines and grid.
-Add new variations: cylinder2, circlesplit, tile_log, truchet_fill, waves2_radial.
--Bug fixes
-cpow2 was wrong.
-Palettes with rapid changes in color would produce slightly different outputs from Apo/Chaotica. This was due to a long standing bug from flam3.
-Use exec() on Apple and show() on all other OSes for dialog boxes.
-Trying to render a sequence with no frames would crash.
-Selecting multiple xforms and rotating them would produce the wrong rotation.
-Better handling when parsing flames using different encoding, such as unicode and UTF-8.
-Switching between SP/DP didn't reselect the selected flame in the Library tab.
--Code changes
-Make all types concerning palettes be floats, including PaletteTableWidgetItem.
-PaletteTableWidgetItem is no longer templated because all palettes are float.
-Include the source colors for user created gradients.
-Change parallel_for() calls to work with very old versions of TBB which are lingering on some systems.
-Split conditional out of accumulation loop on the CPU for better performance.
-Vectorize summing when doing density filter for better performance.
-Make all usage of palettes be of type float, double is pointless.
-Allow palettes to reside in multiple folders, while ensuring only one of each name is added.
-Refactor some palette path searching code.
-Make ReadFile() throw and catch an exception if the file operation fails.
-A little extra safety in foci and foci3D with a call to Zeps().
-Cast to (real_t) in the OpenCL string for the w variation, which was having trouble compiling on Mac.
-Fixing missing comma between paths in InitPaletteList().
-Move Xml and PaletteList classes into cpp to shorten build times when working on them.
-Remove default param values for IterOpenCLKernelCreator<T>::SharedDataIndexDefines in cpp file.
-Change more NULL to nullptr.
2017-02-26 03:02:21 -05:00
m_CarToRas . Convert ( p , histIndex ) ;
//There is a very slim chance that a point will be right on the border and will technically be in bounds, passing the InBounds() test,
//but ends up being mapped to a histogram bucket that is out of bounds due to roundoff error. Perform one final check before proceeding.
//This will result in a few points at the very edges getting discarded, but prevents a crash and doesn't seem to make a speed difference.
if ( histIndex < histSize )
2014-07-08 03:11:14 -04:00
{
--User changes
-Add a palette editor.
-Add support for reading .ugr/.gradient/.gradients palette files.
-Allow toggling on spinners whose minimum value is not zero.
-Allow toggling display of image, affines and grid.
-Add new variations: cylinder2, circlesplit, tile_log, truchet_fill, waves2_radial.
--Bug fixes
-cpow2 was wrong.
-Palettes with rapid changes in color would produce slightly different outputs from Apo/Chaotica. This was due to a long standing bug from flam3.
-Use exec() on Apple and show() on all other OSes for dialog boxes.
-Trying to render a sequence with no frames would crash.
-Selecting multiple xforms and rotating them would produce the wrong rotation.
-Better handling when parsing flames using different encoding, such as unicode and UTF-8.
-Switching between SP/DP didn't reselect the selected flame in the Library tab.
--Code changes
-Make all types concerning palettes be floats, including PaletteTableWidgetItem.
-PaletteTableWidgetItem is no longer templated because all palettes are float.
-Include the source colors for user created gradients.
-Change parallel_for() calls to work with very old versions of TBB which are lingering on some systems.
-Split conditional out of accumulation loop on the CPU for better performance.
-Vectorize summing when doing density filter for better performance.
-Make all usage of palettes be of type float, double is pointless.
-Allow palettes to reside in multiple folders, while ensuring only one of each name is added.
-Refactor some palette path searching code.
-Make ReadFile() throw and catch an exception if the file operation fails.
-A little extra safety in foci and foci3D with a call to Zeps().
-Cast to (real_t) in the OpenCL string for the w variation, which was having trouble compiling on Mac.
-Fixing missing comma between paths in InitPaletteList().
-Move Xml and PaletteList classes into cpp to shorten build times when working on them.
-Remove default param values for IterOpenCLKernelCreator<T>::SharedDataIndexDefines in cpp file.
-Change more NULL to nullptr.
2017-02-26 03:02:21 -05:00
colorIndex = bucketT ( p . m_ColorX ) * COLORMAP_LENGTH_MINUS_1 ;
2014-12-07 02:51:44 -05:00
intColorIndex = size_t ( colorIndex ) ;
2014-07-08 03:11:14 -04:00
if ( intColorIndex < 0 )
{
intColorIndex = 0 ;
colorIndexFrac = 0 ;
}
else if ( intColorIndex > = COLORMAP_LENGTH_MINUS_1 )
{
intColorIndex = COLORMAP_LENGTH_MINUS_1 - 1 ;
colorIndexFrac = 1 ;
}
else
{
2014-12-07 02:51:44 -05:00
colorIndexFrac = colorIndex - bucketT ( intColorIndex ) ; //Interpolate between intColorIndex and intColorIndex + 1.
2014-07-08 03:11:14 -04:00
}
2014-09-10 01:41:26 -04:00
2016-12-05 22:04:33 -05:00
bucketT * __restrict hist = glm : : value_ptr ( m_HistBuckets [ histIndex ] ) ; //Vectorizer can't tell these point to different locations.
const bucketT * __restrict pal = glm : : value_ptr ( palette - > m_Entries [ intColorIndex ] ) ;
const bucketT * __restrict pal2 = glm : : value_ptr ( palette - > m_Entries [ intColorIndex + 1 ] ) ;
auto cifm1 = bucketT ( 1 ) - colorIndexFrac ;
//Loops are unrolled to allow auto vectorization.
2017-03-27 21:05:06 -04:00
if ( p . m_Opacity = = 1 )
2016-12-05 22:04:33 -05:00
{
hist [ 0 ] + = ( pal [ 0 ] * cifm1 ) + ( pal2 [ 0 ] * colorIndexFrac ) ;
hist [ 1 ] + = ( pal [ 1 ] * cifm1 ) + ( pal2 [ 1 ] * colorIndexFrac ) ;
hist [ 2 ] + = ( pal [ 2 ] * cifm1 ) + ( pal2 [ 2 ] * colorIndexFrac ) ;
hist [ 3 ] + = ( pal [ 3 ] * cifm1 ) + ( pal2 [ 3 ] * colorIndexFrac ) ;
}
2014-07-08 03:11:14 -04:00
else
2016-12-05 22:04:33 -05:00
{
2017-03-27 21:05:06 -04:00
auto va = bucketT ( p . m_Opacity ) ;
2016-12-05 22:04:33 -05:00
hist [ 0 ] + = ( ( pal [ 0 ] * cifm1 ) + ( pal2 [ 0 ] * colorIndexFrac ) ) * va ;
hist [ 1 ] + = ( ( pal [ 1 ] * cifm1 ) + ( pal2 [ 1 ] * colorIndexFrac ) ) * va ;
hist [ 2 ] + = ( ( pal [ 2 ] * cifm1 ) + ( pal2 [ 2 ] * colorIndexFrac ) ) * va ;
hist [ 3 ] + = ( ( pal [ 3 ] * cifm1 ) + ( pal2 [ 3 ] * colorIndexFrac ) ) * va ;
}
2014-07-08 03:11:14 -04:00
}
--User changes
-Add a palette editor.
-Add support for reading .ugr/.gradient/.gradients palette files.
-Allow toggling on spinners whose minimum value is not zero.
-Allow toggling display of image, affines and grid.
-Add new variations: cylinder2, circlesplit, tile_log, truchet_fill, waves2_radial.
--Bug fixes
-cpow2 was wrong.
-Palettes with rapid changes in color would produce slightly different outputs from Apo/Chaotica. This was due to a long standing bug from flam3.
-Use exec() on Apple and show() on all other OSes for dialog boxes.
-Trying to render a sequence with no frames would crash.
-Selecting multiple xforms and rotating them would produce the wrong rotation.
-Better handling when parsing flames using different encoding, such as unicode and UTF-8.
-Switching between SP/DP didn't reselect the selected flame in the Library tab.
--Code changes
-Make all types concerning palettes be floats, including PaletteTableWidgetItem.
-PaletteTableWidgetItem is no longer templated because all palettes are float.
-Include the source colors for user created gradients.
-Change parallel_for() calls to work with very old versions of TBB which are lingering on some systems.
-Split conditional out of accumulation loop on the CPU for better performance.
-Vectorize summing when doing density filter for better performance.
-Make all usage of palettes be of type float, double is pointless.
-Allow palettes to reside in multiple folders, while ensuring only one of each name is added.
-Refactor some palette path searching code.
-Make ReadFile() throw and catch an exception if the file operation fails.
-A little extra safety in foci and foci3D with a call to Zeps().
-Cast to (real_t) in the OpenCL string for the w variation, which was having trouble compiling on Mac.
-Fixing missing comma between paths in InitPaletteList().
-Move Xml and PaletteList classes into cpp to shorten build times when working on them.
-Remove default param values for IterOpenCLKernelCreator<T>::SharedDataIndexDefines in cpp file.
-Change more NULL to nullptr.
2017-02-26 03:02:21 -05:00
}
}
}
}
else if ( PaletteMode ( ) = = ePaletteMode : : PALETTE_STEP ) //Duplicate of above, but for step mode.
{
for ( size_t i = 0 ; i < sampleCount & & ! m_Abort ; i + + )
{
Point < T > p ( samples [ i ] ) ; //Slightly faster to cache this.
2017-03-27 21:05:06 -04:00
if ( p . m_Opacity ! = 0 )
--User changes
-Add a palette editor.
-Add support for reading .ugr/.gradient/.gradients palette files.
-Allow toggling on spinners whose minimum value is not zero.
-Allow toggling display of image, affines and grid.
-Add new variations: cylinder2, circlesplit, tile_log, truchet_fill, waves2_radial.
--Bug fixes
-cpow2 was wrong.
-Palettes with rapid changes in color would produce slightly different outputs from Apo/Chaotica. This was due to a long standing bug from flam3.
-Use exec() on Apple and show() on all other OSes for dialog boxes.
-Trying to render a sequence with no frames would crash.
-Selecting multiple xforms and rotating them would produce the wrong rotation.
-Better handling when parsing flames using different encoding, such as unicode and UTF-8.
-Switching between SP/DP didn't reselect the selected flame in the Library tab.
--Code changes
-Make all types concerning palettes be floats, including PaletteTableWidgetItem.
-PaletteTableWidgetItem is no longer templated because all palettes are float.
-Include the source colors for user created gradients.
-Change parallel_for() calls to work with very old versions of TBB which are lingering on some systems.
-Split conditional out of accumulation loop on the CPU for better performance.
-Vectorize summing when doing density filter for better performance.
-Make all usage of palettes be of type float, double is pointless.
-Allow palettes to reside in multiple folders, while ensuring only one of each name is added.
-Refactor some palette path searching code.
-Make ReadFile() throw and catch an exception if the file operation fails.
-A little extra safety in foci and foci3D with a call to Zeps().
-Cast to (real_t) in the OpenCL string for the w variation, which was having trouble compiling on Mac.
-Fixing missing comma between paths in InitPaletteList().
-Move Xml and PaletteList classes into cpp to shorten build times when working on them.
-Remove default param values for IterOpenCLKernelCreator<T>::SharedDataIndexDefines in cpp file.
-Change more NULL to nullptr.
2017-02-26 03:02:21 -05:00
{
2017-03-27 21:05:06 -04:00
if ( Rotate ( ) ! = 0 )
{
T p00 = p . m_X - CenterX ( ) ;
T p11 = p . m_Y - m_Ember . m_RotCenterY ;
p . m_X = ( p00 * m_RotMat . A ( ) ) + ( p11 * m_RotMat . B ( ) ) + CenterX ( ) ;
p . m_Y = ( p00 * m_RotMat . D ( ) ) + ( p11 * m_RotMat . E ( ) ) + m_Ember . m_RotCenterY ;
}
--User changes
-Add a palette editor.
-Add support for reading .ugr/.gradient/.gradients palette files.
-Allow toggling on spinners whose minimum value is not zero.
-Allow toggling display of image, affines and grid.
-Add new variations: cylinder2, circlesplit, tile_log, truchet_fill, waves2_radial.
--Bug fixes
-cpow2 was wrong.
-Palettes with rapid changes in color would produce slightly different outputs from Apo/Chaotica. This was due to a long standing bug from flam3.
-Use exec() on Apple and show() on all other OSes for dialog boxes.
-Trying to render a sequence with no frames would crash.
-Selecting multiple xforms and rotating them would produce the wrong rotation.
-Better handling when parsing flames using different encoding, such as unicode and UTF-8.
-Switching between SP/DP didn't reselect the selected flame in the Library tab.
--Code changes
-Make all types concerning palettes be floats, including PaletteTableWidgetItem.
-PaletteTableWidgetItem is no longer templated because all palettes are float.
-Include the source colors for user created gradients.
-Change parallel_for() calls to work with very old versions of TBB which are lingering on some systems.
-Split conditional out of accumulation loop on the CPU for better performance.
-Vectorize summing when doing density filter for better performance.
-Make all usage of palettes be of type float, double is pointless.
-Allow palettes to reside in multiple folders, while ensuring only one of each name is added.
-Refactor some palette path searching code.
-Make ReadFile() throw and catch an exception if the file operation fails.
-A little extra safety in foci and foci3D with a call to Zeps().
-Cast to (real_t) in the OpenCL string for the w variation, which was having trouble compiling on Mac.
-Fixing missing comma between paths in InitPaletteList().
-Move Xml and PaletteList classes into cpp to shorten build times when working on them.
-Remove default param values for IterOpenCLKernelCreator<T>::SharedDataIndexDefines in cpp file.
-Change more NULL to nullptr.
2017-02-26 03:02:21 -05:00
2017-03-27 21:05:06 -04:00
if ( m_CarToRas . InBounds ( p ) )
--User changes
-Add a palette editor.
-Add support for reading .ugr/.gradient/.gradients palette files.
-Allow toggling on spinners whose minimum value is not zero.
-Allow toggling display of image, affines and grid.
-Add new variations: cylinder2, circlesplit, tile_log, truchet_fill, waves2_radial.
--Bug fixes
-cpow2 was wrong.
-Palettes with rapid changes in color would produce slightly different outputs from Apo/Chaotica. This was due to a long standing bug from flam3.
-Use exec() on Apple and show() on all other OSes for dialog boxes.
-Trying to render a sequence with no frames would crash.
-Selecting multiple xforms and rotating them would produce the wrong rotation.
-Better handling when parsing flames using different encoding, such as unicode and UTF-8.
-Switching between SP/DP didn't reselect the selected flame in the Library tab.
--Code changes
-Make all types concerning palettes be floats, including PaletteTableWidgetItem.
-PaletteTableWidgetItem is no longer templated because all palettes are float.
-Include the source colors for user created gradients.
-Change parallel_for() calls to work with very old versions of TBB which are lingering on some systems.
-Split conditional out of accumulation loop on the CPU for better performance.
-Vectorize summing when doing density filter for better performance.
-Make all usage of palettes be of type float, double is pointless.
-Allow palettes to reside in multiple folders, while ensuring only one of each name is added.
-Refactor some palette path searching code.
-Make ReadFile() throw and catch an exception if the file operation fails.
-A little extra safety in foci and foci3D with a call to Zeps().
-Cast to (real_t) in the OpenCL string for the w variation, which was having trouble compiling on Mac.
-Fixing missing comma between paths in InitPaletteList().
-Move Xml and PaletteList classes into cpp to shorten build times when working on them.
-Remove default param values for IterOpenCLKernelCreator<T>::SharedDataIndexDefines in cpp file.
-Change more NULL to nullptr.
2017-02-26 03:02:21 -05:00
{
m_CarToRas . Convert ( p , histIndex ) ;
if ( histIndex < histSize )
2014-07-08 03:11:14 -04:00
{
--User changes
-Add a palette editor.
-Add support for reading .ugr/.gradient/.gradients palette files.
-Allow toggling on spinners whose minimum value is not zero.
-Allow toggling display of image, affines and grid.
-Add new variations: cylinder2, circlesplit, tile_log, truchet_fill, waves2_radial.
--Bug fixes
-cpow2 was wrong.
-Palettes with rapid changes in color would produce slightly different outputs from Apo/Chaotica. This was due to a long standing bug from flam3.
-Use exec() on Apple and show() on all other OSes for dialog boxes.
-Trying to render a sequence with no frames would crash.
-Selecting multiple xforms and rotating them would produce the wrong rotation.
-Better handling when parsing flames using different encoding, such as unicode and UTF-8.
-Switching between SP/DP didn't reselect the selected flame in the Library tab.
--Code changes
-Make all types concerning palettes be floats, including PaletteTableWidgetItem.
-PaletteTableWidgetItem is no longer templated because all palettes are float.
-Include the source colors for user created gradients.
-Change parallel_for() calls to work with very old versions of TBB which are lingering on some systems.
-Split conditional out of accumulation loop on the CPU for better performance.
-Vectorize summing when doing density filter for better performance.
-Make all usage of palettes be of type float, double is pointless.
-Allow palettes to reside in multiple folders, while ensuring only one of each name is added.
-Refactor some palette path searching code.
-Make ReadFile() throw and catch an exception if the file operation fails.
-A little extra safety in foci and foci3D with a call to Zeps().
-Cast to (real_t) in the OpenCL string for the w variation, which was having trouble compiling on Mac.
-Fixing missing comma between paths in InitPaletteList().
-Move Xml and PaletteList classes into cpp to shorten build times when working on them.
-Remove default param values for IterOpenCLKernelCreator<T>::SharedDataIndexDefines in cpp file.
-Change more NULL to nullptr.
2017-02-26 03:02:21 -05:00
intColorIndex = Clamp < size_t > ( size_t ( p . m_ColorX * COLORMAP_LENGTH_MINUS_1 ) , 0 , COLORMAP_LENGTH_MINUS_1 ) ;
2016-12-05 22:04:33 -05:00
bucketT * __restrict hist = glm : : value_ptr ( m_HistBuckets [ histIndex ] ) ; //Vectorizer can't tell these point to different locations.
const bucketT * __restrict pal = glm : : value_ptr ( palette - > m_Entries [ intColorIndex ] ) ;
2014-07-08 03:11:14 -04:00
2017-03-27 21:05:06 -04:00
if ( p . m_Opacity = = 1 )
2016-12-05 22:04:33 -05:00
{
hist [ 0 ] + = pal [ 0 ] ;
hist [ 1 ] + = pal [ 1 ] ;
hist [ 2 ] + = pal [ 2 ] ;
hist [ 3 ] + = pal [ 3 ] ;
}
2014-07-08 03:11:14 -04:00
else
2016-12-05 22:04:33 -05:00
{
2017-03-27 21:05:06 -04:00
auto va = bucketT ( p . m_Opacity ) ;
2016-12-05 22:04:33 -05:00
hist [ 0 ] + = pal [ 0 ] * va ;
hist [ 1 ] + = pal [ 1 ] * va ;
hist [ 2 ] + = pal [ 2 ] * va ;
hist [ 3 ] + = pal [ 3 ] * va ;
}
2014-07-08 03:11:14 -04:00
}
}
}
}
}
}
/// <summary>
/// Add a value to the density filtering buffer with a bounds check.
/// </summary>
/// <param name="bucket">The bucket being filtered</param>
/// <param name="i">The column of the bucket</param>
/// <param name="ii">The offset to add to the column</param>
/// <param name="j">The row of the bucket</param>
/// <param name="jj">The offset to add to the row</param>
template < typename T , typename bucketT >
2015-03-21 18:27:37 -04:00
void Renderer < T , bucketT > : : AddToAccum ( const tvec4 < bucketT , glm : : defaultp > & bucket , intmax_t i , intmax_t ii , intmax_t j , intmax_t jj )
2014-07-08 03:11:14 -04:00
{
2014-12-07 02:51:44 -05:00
if ( j + jj > = 0 & & j + jj < intmax_t ( m_SuperRasH ) & & i + ii > = 0 & & i + ii < intmax_t ( m_SuperRasW ) )
--User changes
-Add a palette editor.
-Add support for reading .ugr/.gradient/.gradients palette files.
-Allow toggling on spinners whose minimum value is not zero.
-Allow toggling display of image, affines and grid.
-Add new variations: cylinder2, circlesplit, tile_log, truchet_fill, waves2_radial.
--Bug fixes
-cpow2 was wrong.
-Palettes with rapid changes in color would produce slightly different outputs from Apo/Chaotica. This was due to a long standing bug from flam3.
-Use exec() on Apple and show() on all other OSes for dialog boxes.
-Trying to render a sequence with no frames would crash.
-Selecting multiple xforms and rotating them would produce the wrong rotation.
-Better handling when parsing flames using different encoding, such as unicode and UTF-8.
-Switching between SP/DP didn't reselect the selected flame in the Library tab.
--Code changes
-Make all types concerning palettes be floats, including PaletteTableWidgetItem.
-PaletteTableWidgetItem is no longer templated because all palettes are float.
-Include the source colors for user created gradients.
-Change parallel_for() calls to work with very old versions of TBB which are lingering on some systems.
-Split conditional out of accumulation loop on the CPU for better performance.
-Vectorize summing when doing density filter for better performance.
-Make all usage of palettes be of type float, double is pointless.
-Allow palettes to reside in multiple folders, while ensuring only one of each name is added.
-Refactor some palette path searching code.
-Make ReadFile() throw and catch an exception if the file operation fails.
-A little extra safety in foci and foci3D with a call to Zeps().
-Cast to (real_t) in the OpenCL string for the w variation, which was having trouble compiling on Mac.
-Fixing missing comma between paths in InitPaletteList().
-Move Xml and PaletteList classes into cpp to shorten build times when working on them.
-Remove default param values for IterOpenCLKernelCreator<T>::SharedDataIndexDefines in cpp file.
-Change more NULL to nullptr.
2017-02-26 03:02:21 -05:00
{
auto * __restrict accum = m_AccumulatorBuckets . data ( ) + ( ( i + ii ) + ( ( j + jj ) * m_SuperRasW ) ) ; //For vectorizer, results in a 33% speedup.
accum - > r + = bucket . r ;
accum - > g + = bucket . g ;
accum - > b + = bucket . b ;
accum - > a + = bucket . a ;
}
2014-07-08 03:11:14 -04:00
}
/// <summary>
/// Clip and gamma correct a pixel.
/// Because this code is used in both early and late clipping, a few extra arguments are passed
/// to specify what actions to take. Coupled with an additional template argument, this allows
/// using one function to perform all color clipping, gamma correction and final accumulation.
2017-07-22 16:43:35 -04:00
/// Template argument accumT is expected to always be float4.
2014-07-08 03:11:14 -04:00
/// </summary>
/// <param name="bucket">The pixel to correct</param>
/// <param name="background">The background color</param>
/// <param name="g">The gamma to use</param>
/// <param name="linRange">The linear range to use</param>
/// <param name="vibrancy">The vibrancy to use</param>
/// <param name="scale">True if late clip, else false.</param>
/// <param name="correctedChannels">The storage space for the corrected values to be written to</param>
template < typename T , typename bucketT >
template < typename accumT >
2017-07-22 16:43:35 -04:00
void Renderer < T , bucketT > : : GammaCorrection ( tvec4 < bucketT , glm : : defaultp > & bucket , Color < bucketT > & background , bucketT g , bucketT linRange , bucketT vibrancy , bool scale , accumT * correctedChannels )
2014-07-08 03:11:14 -04:00
{
2017-07-22 16:43:35 -04:00
auto bt1 = bucketT ( 1 ) ;
2014-07-08 03:11:14 -04:00
2017-07-22 16:43:35 -04:00
if ( scale & & EarlyClip ( ) )
2014-07-08 03:11:14 -04:00
{
2017-07-22 16:43:35 -04:00
if ( m_CurvesSet )
{
CurveAdjust ( bucket . r , 1 ) ;
CurveAdjust ( bucket . g , 2 ) ;
CurveAdjust ( bucket . b , 3 ) ;
}
correctedChannels [ 0 ] = accumT ( Clamp < bucketT > ( bucket . r , 0 , bt1 ) ) ;
correctedChannels [ 1 ] = accumT ( Clamp < bucketT > ( bucket . g , 0 , bt1 ) ) ;
correctedChannels [ 2 ] = accumT ( Clamp < bucketT > ( bucket . b , 0 , bt1 ) ) ;
correctedChannels [ 3 ] = accumT ( Clamp < bucketT > ( bucket . a , 0 , bt1 ) ) ;
2014-07-08 03:11:14 -04:00
}
else
{
2017-07-22 16:43:35 -04:00
bucketT alpha , ls , a , newRgb [ 3 ] ; //Would normally use a Color<bucketT>, but don't want to call a needless constructor every time this function is called, which is once per pixel.
2014-07-08 03:11:14 -04:00
2017-07-22 16:43:35 -04:00
if ( bucket . a < = 0 )
2014-07-08 03:11:14 -04:00
{
2017-07-22 16:43:35 -04:00
alpha = 0 ;
ls = 0 ;
2014-07-08 03:11:14 -04:00
}
else
{
2017-07-22 16:43:35 -04:00
alpha = Palette < bucketT > : : CalcAlpha ( bucket . a , g , linRange ) ;
ls = vibrancy * alpha / bucket . a ;
ClampRef < bucketT > ( alpha , 0 , 1 ) ;
2014-07-08 03:11:14 -04:00
}
2017-07-22 16:43:35 -04:00
Palette < bucketT > : : template CalcNewRgb < bucketT > ( glm : : value_ptr ( bucket ) , ls , HighlightPower ( ) , newRgb ) ;
for ( glm : : length_t rgbi = 0 ; rgbi < 3 ; rgbi + + )
2015-03-21 18:27:37 -04:00
{
2017-07-22 16:43:35 -04:00
a = newRgb [ rgbi ] + ( ( 1 - vibrancy ) * std : : pow ( std : : abs ( bucket [ rgbi ] ) , g ) ) ; //Must use abs(), else it it could be a negative value and return NAN.
a + = ( 1 - alpha ) * background [ rgbi ] ;
2017-07-05 02:08:06 -04:00
2017-07-22 16:43:35 -04:00
if ( scale & & m_CurvesSet )
2015-03-21 18:27:37 -04:00
CurveAdjust ( a , rgbi + 1 ) ;
2017-07-22 16:43:35 -04:00
correctedChannels [ rgbi ] = accumT ( Clamp < bucketT > ( a , 0 , bt1 ) ) ; //Early clip, just assign directly.
2015-03-21 18:27:37 -04:00
}
2014-07-08 03:11:14 -04:00
2017-07-22 16:43:35 -04:00
correctedChannels [ 3 ] = accumT ( alpha ) ;
2014-07-08 03:11:14 -04:00
}
}
2014-12-05 21:30:46 -05:00
2017-07-05 02:08:06 -04:00
/// <summary>
/// Setup the curve values when they are being used.
/// </summary>
template < typename T , typename bucketT >
2017-07-22 16:43:35 -04:00
void Renderer < T , bucketT > : : ComputeCurves ( )
2017-07-05 02:08:06 -04:00
{
if ( m_CurvesSet )
{
2017-07-23 01:24:04 -04:00
//Timing t;
2017-07-05 02:08:06 -04:00
auto st = m_Csa . size ( ) ;
for ( size_t i = 0 ; i < st ; i + + )
2017-07-22 16:43:35 -04:00
m_Csa [ i ] = m_Ember . m_Curves . BezierFunc ( i * ONE_OVER_CURVES_LENGTH_M1 ) ;
2017-07-23 01:24:04 -04:00
//t.Toc("ComputeCurves");
2017-07-05 02:08:06 -04:00
}
}
/// <summary>
/// Apply the curve adjustment to a single channel.
/// </summary>
2017-07-22 16:43:35 -04:00
/// <param name="aScaled">The value of the channel to apply curve adjustment to.</param>
2017-07-05 02:08:06 -04:00
/// <param name="index">The index of the channel to apply curve adjustment to</param>
2015-03-21 18:27:37 -04:00
template < typename T , typename bucketT >
2017-07-22 16:43:35 -04:00
void Renderer < T , bucketT > : : CurveAdjust ( bucketT & a , const glm : : length_t & index )
2015-03-21 18:27:37 -04:00
{
2017-07-22 16:43:35 -04:00
size_t tempIndex = size_t ( Clamp < bucketT > ( a * CURVES_LENGTH_M1 , 0 , CURVES_LENGTH_M1 ) ) ;
size_t tempIndex2 = size_t ( Clamp < bucketT > ( m_Csa [ tempIndex ] . x * CURVES_LENGTH_M1 , 0 , CURVES_LENGTH_M1 ) ) ;
a = m_Csa [ tempIndex2 ] [ index ] ;
2015-03-21 18:27:37 -04:00
}
2014-12-05 21:30:46 -05:00
//This class had to be implemented in a cpp file because the compiler was breaking.
//So the explicit instantiation must be declared here rather than in Ember.cpp where
//all of the other classes are done.
template EMBER_API class Renderer < float , float > ;
2016-04-03 21:55:12 -04:00
template EMBER_API void Renderer < float , float > : : SetEmber ( const vector < Ember < float > > & embers ) ;
template EMBER_API void Renderer < float , float > : : SetEmber ( const list < Ember < float > > & embers ) ;
2014-12-05 21:30:46 -05:00
# ifdef DO_DOUBLE
2015-08-10 23:10:23 -04:00
template EMBER_API class Renderer < double , float > ;
2016-04-03 21:55:12 -04:00
template EMBER_API void Renderer < double , float > : : SetEmber ( const vector < Ember < double > > & embers ) ;
template EMBER_API void Renderer < double , float > : : SetEmber ( const list < Ember < double > > & embers ) ;
2014-12-05 21:30:46 -05:00
# endif
2014-09-10 01:41:26 -04:00
}