// 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);
};