#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 must always be float. /// 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 ComputeQuality() override; virtual void ComputeCamera() override; virtual void SetEmber(Ember& ember, eProcessAction action = eProcessAction::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(tvec4); } virtual eRenderStatus Run(vector& finalImage, double time = 0, size_t subBatchCountOverride = 0, bool forceOutput = false, size_t finalOffset = 0) override; virtual EmberImageComments ImageComments(const 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(bool histOnly = false); virtual bool ResetBuckets(bool resetHist = true, bool resetAccum = true); virtual eRenderStatus LogScaleDensityFilter(bool forceOutput = false); virtual eRenderStatus GaussianDensityFilter(); virtual eRenderStatus AccumulatorToFinalImage(vector& pixels, size_t finalOffset); virtual eRenderStatus AccumulatorToFinalImage(byte* 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 bucketT K1() const; inline bucketT K2() const; inline const CarToRas& CoordMap() const; inline tvec4* HistBuckets(); inline 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 bucketT Brightness() const; inline bucketT Contrast() const; inline bucketT Gamma() const; inline bucketT Vibrancy() const; inline bucketT GammaThresh() const; inline bucketT 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 byte* XformDistributions() 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, bucketT& g, bucketT& linRange, bucketT& 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 tvec4& bucket, intmax_t i, intmax_t ii, intmax_t j, intmax_t jj); template void GammaCorrection(tvec4& bucket, Color& background, bucketT g, bucketT linRange, bucketT vibrancy, bool doAlpha, bool scale, accumT* correctedChannels); void CurveAdjust(bucketT& a, const glm::length_t& index); void VectorizedLogScale(size_t row, size_t rowEnd); 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; bucketT m_K1; bucketT m_K2; bucketT m_Vibrancy;//Accumulate these after each temporal sample. bucketT m_Gamma; T m_ScaledQuality; Color m_Background;//This is a scaled copy of the m_Background member of m_Ember, but with a type of bucketT. Affine2D m_RotMat; Ember m_Ember; Ember m_TempEmber; Ember m_LastEmber; vector> m_Embers; vector> m_ThreadEmbers; CarToRas m_CarToRas; Iterator* m_Iterator; unique_ptr> m_StandardIterator; unique_ptr> m_XaosIterator; Palette m_Dmap, m_Csa; 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. }