#pragma once
#include "RendererBase.h"
#include "Iterator.h"
#include "SpatialFilter.h"
#include "TemporalFilter.h"
#include "Interpolate.h"
#include "CarToRas.h"
#include "EmberToXml.h"
///
/// Renderer.
///
namespace EmberNs
{
///
/// Renderer is the main class where all of the execution takes place.
/// It is intended that the program have one instance of it that it
/// keeps around for its duration. After a user sets up an ember, it's passed
/// in to be rendered.
/// This class derives from EmberReport, so the caller is able
/// to retrieve a text dump of error information if any errors occur.
/// The final image output vector is also passed in because the calling code has more
/// use for it than this class does.
/// Several functions are made virtual and have a default CPU-based implementation
/// that roughly matches what flam3 did. However they can be overridden in derived classes
/// to provide alternative rendering implementations, such as using the GPU.
/// Since this is a templated class, it's supposed to be entirely implemented in this .h file.
/// However, VC++ 2010 has very crippled support for lambdas, which Renderer makes use of.
/// If too many lambdas are used in a .h file, it will crash the compiler when another library
/// tries to link to it. To work around the bug, only declarations are here and all implementations
/// are in the .cpp file. It's unclear at what point it starts/stops working. But it seems that once
/// enough code is placed in the .h file, the compiler crashes. So for the sake of consistency, everything
/// is moved to the .cpp, even simple getters. One drawback however, is that the class must be
/// explicitly exported at the bottom of the file.
/// Also, despite explicitly doing this, the compiler throws a C4661 warning
/// for every single function in this class, saying it can't find the implementation. This warning
/// can be safely ignored.
/// Template argument T expected to be float or double.
/// Template argument bucketT was originally used to experiment with different types for the histogram, however
/// the only types that work are float and double, so it's useless and should always match what T is.
/// Mismatched types between T and bucketT are undefined.
///
template
class EMBER_API Renderer : public RendererBase
{
//using EmberReport::m_ErrorReport;
public:
Renderer();
virtual ~Renderer();
//Non-virtual processing functions.
void AddEmber(Ember& ember);
bool AssignIterator();
//Virtual processing functions overriden from RendererBase.
virtual void ComputeBounds() override;
virtual void ComputeCamera() override;
virtual void SetEmber(Ember& ember, eProcessAction action = FULL_RENDER) override;
virtual void SetEmber(vector>& embers) override;
virtual bool CreateDEFilter(bool& newAlloc) override;
virtual bool CreateSpatialFilter(bool& newAlloc) override;
virtual bool CreateTemporalFilter(bool& newAlloc) override;
virtual size_t HistBucketSize() const override { return sizeof(glm::detail::tvec4); }
virtual eRenderStatus Run(vector& finalImage, double time = 0, size_t subBatchCountOverride = 0, bool forceOutput = false, size_t finalOffset = 0) override;
virtual EmberImageComments ImageComments(EmberStats& stats, size_t printEditDepth = 0, bool intPalette = false, bool hexPalette = true) override;
protected:
//New virtual functions to be overridden in derived renderers that use the GPU, but not accessed outside.
virtual void MakeDmap(T colorScalar);
virtual bool Alloc();
virtual bool ResetBuckets(bool resetHist = true, bool resetAccum = true);
virtual eRenderStatus LogScaleDensityFilter();
virtual eRenderStatus GaussianDensityFilter();
virtual eRenderStatus AccumulatorToFinalImage(vector& pixels, size_t finalOffset);
virtual eRenderStatus AccumulatorToFinalImage(unsigned char* pixels, size_t finalOffset);
virtual EmberStats Iterate(size_t iterCount, size_t temporalSample);
public:
//Non-virtual render properties, getters and setters.
inline T PixelAspectRatio() const;
void PixelAspectRatio(T pixelAspectRatio);
//Non-virtual renderer properties, getters only.
inline T Scale() const;
inline T PixelsPerUnitX() const;
inline T PixelsPerUnitY() const;
inline T K1() const;
inline T K2() const;
inline const CarToRas* CoordMap() const;
inline glm::detail::tvec4* HistBuckets();
inline glm::detail::tvec4* AccumulatorBuckets();
inline SpatialFilter* GetSpatialFilter();
inline TemporalFilter* GetTemporalFilter();
//Virtual renderer properties overridden from RendererBase, getters only.
virtual double ScaledQuality() const override;
virtual double LowerLeftX(bool gutter = true) const override;
virtual double LowerLeftY(bool gutter = true) const override;
virtual double UpperRightX(bool gutter = true) const override;
virtual double UpperRightY(bool gutter = true) const override;
virtual DensityFilterBase* GetDensityFilter() override;
//Non-virtual ember wrappers, getters only.
inline bool XaosPresent() const;
inline size_t Supersample() const;
inline size_t PaletteIndex() const;
inline T Time() const;
inline T Quality() const;
inline T SpatialFilterRadius() const;
inline T PixelsPerUnit() const;
inline T Zoom() const;
inline T CenterX() const;
inline T CenterY() const;
inline T Rotate() const;
inline T Hue() const;
inline T Brightness() const;
inline T Contrast() const;
inline T Gamma() const;
inline T Vibrancy() const;
inline T GammaThresh() const;
inline T HighlightPower() const;
inline Color Background() const;
inline const Xform* Xforms() const;
inline Xform* NonConstXforms();
inline size_t XformCount() const;
inline const Xform* FinalXform() const;
inline Xform* NonConstFinalXform();
inline bool UseFinalXform() const;
inline const Palette* GetPalette() const;
inline ePaletteMode PaletteMode() const;
//Virtual ember wrappers overridden from RendererBase, getters only.
virtual size_t TemporalSamples() const override;
virtual size_t FinalRasW() const override;
virtual size_t FinalRasH() const override;
virtual size_t SubBatchSize() const override;
virtual size_t FuseCount() const override;
//Non-virtual iterator wrappers.
const unsigned char* XformDistributions() const;
const size_t XformDistributionsSize() const;
Point* Samples(size_t threadIndex) const;
protected:
//Non-virtual functions that might be needed by a derived class.
void PrepFinalAccumVals(Color& background, T& g, T& linRange, T& vibrancy);
private:
//Miscellaneous non-virtual functions used only in this class.
void Accumulate(QTIsaac& rand, Point* samples, size_t sampleCount, const Palette* palette);
/*inline*/ void AddToAccum(const glm::detail::tvec4& bucket, intmax_t i, intmax_t ii, intmax_t j, intmax_t jj);
template void GammaCorrection(glm::detail::tvec4& bucket, Color& background, T g, T linRange, T vibrancy, bool doAlpha, bool scale, accumT* correctedChannels);
protected:
T m_Scale;
T m_PixelsPerUnitX;
T m_PixelsPerUnitY;
T m_PixelAspectRatio;
T m_LowerLeftX;
T m_LowerLeftY;
T m_UpperRightX;
T m_UpperRightY;
T m_K1;
T m_K2;
T m_Vibrancy;//Accumulate these after each temporal sample.
T m_Gamma;
T m_ScaledQuality;
Color m_Background;
Affine2D m_RotMat;
Ember m_Ember;
Ember m_TempEmber;
Ember m_LastEmber;
vector> m_Embers;
CarToRas m_CarToRas;
Iterator* m_Iterator;
unique_ptr> m_StandardIterator;
unique_ptr> m_XaosIterator;
Palette m_Dmap;
vector> m_HistBuckets;
vector> m_AccumulatorBuckets;
unique_ptr> m_SpatialFilter;
unique_ptr> m_TemporalFilter;
unique_ptr> m_DensityFilter;
vector>> m_Samples;
EmberToXml m_EmberToXml;
};
//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;
//#ifdef DO_DOUBLE
// template EMBER_API class Renderer;
//#endif
}