// Copyright (c) 2012-2020 Wojciech Figat. All rights reserved. #pragma once #include "Engine/Core/Types/BaseTypes.h" #include "Engine/Core/Collections/Array.h" /// /// To load the IES file image format. IES files exist for many real world lights. The file stores how much light is emitted in a specific direction. /// The data is usually measured but tools to paint IES files exist. /// class IESLoader { private: float _brightness; float _cachedIntegral; Array _hAngles; Array _vAngles; Array _candalaValues; public: /// /// Init /// IESLoader(); public: /// /// Load IES file /// /// Buffer with data /// True if cannot load, otherwise false FORCE_INLINE bool Load(const Array& buffer) { return Load(buffer.Get()); } /// /// Load IES file /// /// Buffer with data /// True if cannot load, otherwise false bool Load(const byte* buffer); public: /// /// Gets width /// /// Width in pixels FORCE_INLINE uint32 GetWidth() const { // We use contant size return 256; } /// /// Gets height /// /// Height in pixels FORCE_INLINE uint32 GetHeight() const { // We use contant size return 1; } /// /// Gets IES profile brightness value in lumens (always > 0) /// /// Brightness (in lumens) FORCE_INLINE float GetBrightness() const { return _brightness; } public: /// /// Extracts IES profile data to R16F format /// /// Result data container /// Multiplier as the texture is normalized float ExtractInR16F(Array& output); public: float InterpolatePoint(int32 X, int32 Y) const; float InterpolateBilinear(float fX, float fY) const; /// /// Compute the Candala value for a given direction /// /// HAngle (in degrees e.g. 0..180) /// VAngle (in degrees e.g. 0..180) /// Sampled value float Interpolate2D(float HAngle, float VAngle) const; /// /// Compute the Candala value for a given direction (integrates over HAngle) /// /// VAngle (in degrees e.g. 0..180) /// Sampled value float Interpolate1D(float VAngle) const; public: /// /// Calculates maximum value /// /// Maximum value float ComputeMax() const; /// /// Integrate over the unit sphere /// /// Integral value float ComputeFullIntegral(); /// /// Computes filtering position for given value in sorted set of values /// /// Value to find /// Value to use /// Filter position static float ComputeFilterPos(float value, const Array& sortedValues); };