Skip to content

Commit

Permalink
Add support for area lights
Browse files Browse the repository at this point in the history
  • Loading branch information
Haneul Kim authored and pixelflinger committed Aug 27, 2024
1 parent f11e5cb commit e064cb8
Show file tree
Hide file tree
Showing 20 changed files with 2,429 additions and 14 deletions.
3 changes: 3 additions & 0 deletions filament/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ set(SRCS
src/IndirectLight.cpp
src/InstanceBuffer.cpp
src/LightManager.cpp
src/LTC.cpp
src/Material.cpp
src/MaterialInstance.cpp
src/MaterialParser.cpp
Expand Down Expand Up @@ -152,6 +153,8 @@ set(PRIVATE_HDRS
src/HwRenderPrimitiveFactory.h
src/HwVertexBufferInfoFactory.h
src/Intersections.h
src/LTC.h
src/ltc.inc
src/MaterialParser.h
src/PerViewUniforms.h
src/PerShadowMapUniforms.h
Expand Down
17 changes: 17 additions & 0 deletions filament/include/filament/LightManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,7 @@ class UTILS_PUBLIC LightManager : public FilamentAPI {
POINT, //!< Point light, emits light from a position, in all directions.
FOCUSED_SPOT, //!< Physically correct spot light.
SPOT, //!< Spot light with coupling of outer cone and illumination disabled.
AREA,
};

/**
Expand Down Expand Up @@ -651,6 +652,10 @@ class UTILS_PUBLIC LightManager : public FilamentAPI {
*/
Builder& sunHaloFalloff(float haloFalloff) noexcept;

Builder& width(float width) noexcept;

Builder& height(float height) noexcept;

enum Result { Error = -1, Success = 0 };

/**
Expand Down Expand Up @@ -719,6 +724,10 @@ class UTILS_PUBLIC LightManager : public FilamentAPI {
return type == Type::SPOT || type == Type::FOCUSED_SPOT;
}

inline bool isAreaLight(Instance i) const noexcept {
return getType(i) == Type::AREA;
}

/**
* Enables or disables a light channel. Light channel 0 is enabled by default.
* @param channel light channel to enable or disable, between 0 and 7.
Expand Down Expand Up @@ -936,6 +945,14 @@ class UTILS_PUBLIC LightManager : public FilamentAPI {
*/
float getSunHaloFalloff(Instance i) const noexcept;

void setWidth(Instance i, float width) noexcept;

float getWidth(Instance i) const noexcept;

void setHeight(Instance i, float height) noexcept;

float getHeight(Instance i) const noexcept;

/**
* returns the shadow-map options for a given light
* @param i Instance of the component obtained from getInstance().
Expand Down
71 changes: 71 additions & 0 deletions filament/src/LTC.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include "LTC.h"

#include "details/Engine.h"
#include "details/Texture.h"

namespace filament {

#include "ltc.inc"

void LTC::init(FEngine& engine) noexcept {
constexpr size_t fp16Count = LTC_LUT_SIZE * LTC_LUT_SIZE * 4;
constexpr size_t byteCount = fp16Count * sizeof(uint16_t);

static_assert(sizeof(LTC_LUT_1) == byteCount, "LTC_LUT_SIZE doesn't match size of the LTC LUT 1");

Texture* lut1 = Texture::Builder()
.width(LTC_LUT_SIZE)
.height(LTC_LUT_SIZE)
.format(backend::TextureFormat::RGBA16F)
.build(engine);

Texture::PixelBufferDescriptor buffer1(LTC_LUT_1, byteCount,
Texture::Format::RGBA, Texture::Type::HALF);

lut1->setImage(engine, 0, std::move(buffer1));

mLUT1 = downcast(lut1);

static_assert(sizeof(LTC_LUT_2) == byteCount, "LTC_LUT_SIZE doesn't match size of the LTC LUT 2");

Texture* ltc2 = Texture::Builder()
.width(LTC_LUT_SIZE)
.height(LTC_LUT_SIZE)
.format(backend::TextureFormat::RGBA16F)
.build(engine);

Texture::PixelBufferDescriptor buffer2(LTC_LUT_2, byteCount,
Texture::Format::RGBA, Texture::Type::HALF);

ltc2->setImage(engine, 0, std::move(buffer2));

mLUT2 = downcast(ltc2);
}

void LTC::terminate(FEngine& engine) noexcept {
if (mLUT1) {
engine.destroy(mLUT1);
}

if (mLUT2) {
engine.destroy(mLUT2);
}
}

} // namespace filament
73 changes: 73 additions & 0 deletions filament/src/LTC.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#ifndef TNT_FILAMENT_DETAILS_LTC_H
#define TNT_FILAMENT_DETAILS_LTC_H

#include <backend/Handle.h>

#include "details/Texture.h"

#include <utils/compiler.h>

namespace filament {

class FEngine;

#define FILAMENT_LTC_LUT_SIZE 64

class LTC {
public:
explicit LTC() noexcept = default;

LTC(LTC const& rhs) = delete;
LTC(LTC&& rhs) = delete;
LTC& operator=(LTC const& rhs) = delete;
LTC& operator=(LTC&& rhs) = delete;

void init(FEngine& engine) noexcept;

size_t getLutSize() const noexcept {
return LTC_LUT_SIZE;
}

bool isValid() const noexcept {
return mLUT1 != nullptr && mLUT2 != nullptr;
}

backend::Handle<backend::HwTexture> getTexture1() const noexcept {
return mLUT1->getHwHandle();
}

backend::Handle<backend::HwTexture> getTexture2() const noexcept {
return mLUT2->getHwHandle();
}

void terminate(FEngine& engine) noexcept;

private:
FTexture* mLUT1 = nullptr;
FTexture* mLUT2 = nullptr;

static constexpr size_t LTC_LUT_SIZE = FILAMENT_LTC_LUT_SIZE;

static const uint16_t LTC_LUT_1[];
static const uint16_t LTC_LUT_2[];
};

} // namespace filament

#endif // TNT_FILAMENT_DETAILS_LTC_H
16 changes: 16 additions & 0 deletions filament/src/LightManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,22 @@ float LightManager::getSunHaloFalloff(Instance i) const noexcept {
return downcast(this)->getSunHaloFalloff(i);
}

void LightManager::setWidth(Instance i, float width) noexcept {
downcast(this)->setWidth(i, width);
}

float LightManager::getWidth(Instance i) const noexcept {
return downcast(this)->getWidth(i);
}

void LightManager::setHeight(Instance i, float height) noexcept {
downcast(this)->setHeight(i, height);
}

float LightManager::getHeight(Instance i) const noexcept {
return downcast(this)->getHeight(i);
}

LightManager::Type LightManager::getType(LightManager::Instance i) const noexcept {
return downcast(this)->getType(i);
}
Expand Down
9 changes: 9 additions & 0 deletions filament/src/PerViewUniforms.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "PerViewUniforms.h"

#include "DFG.h"
#include "LTC.h"
#include "Froxelizer.h"
#include "ShadowMapManager.h"

Expand Down Expand Up @@ -54,6 +55,14 @@ PerViewUniforms::PerViewUniforms(FEngine& engine) noexcept
mSamplers.setSampler(PerViewSib::IBL_DFG_LUT,
{ engine.getDFG().getTexture(), sampler.getSamplerParams() });
}

if (engine.getLTC().isValid()) {
TextureSampler const sampler(TextureSampler::MagFilter::LINEAR);
mSamplers.setSampler(PerViewSib::LTC_LUT_1,
{ engine.getLTC().getTexture1(), sampler.getSamplerParams() });
mSamplers.setSampler(PerViewSib::LTC_LUT_2,
{ engine.getLTC().getTexture2(), sampler.getSamplerParams() });
}
}

void PerViewUniforms::terminate(DriverApi& driver) {
Expand Down
28 changes: 28 additions & 0 deletions filament/src/components/LightManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ struct LightManager::BuilderDetails {
float mSunAngle = 0.00951f; // 0.545° in radians
float mSunHaloSize = 10.0f;
float mSunHaloFalloff = 80.0f;
float mWidth = 1.0f;
float mHeight = 1.0f;
ShadowOptions mShadowOptions;

explicit BuilderDetails(Type type) noexcept : mType(type) { }
Expand Down Expand Up @@ -138,6 +140,16 @@ LightManager::Builder& LightManager::Builder::sunHaloFalloff(float haloFalloff)
return *this;
}

LightManager::Builder& LightManager::Builder::width(float width) noexcept {
mImpl->mWidth = width;
return *this;
}

LightManager::Builder& LightManager::Builder::height(float height) noexcept {
mImpl->mHeight = height;
return *this;
}

LightManager::Builder& LightManager::Builder::lightChannel(unsigned int channel, bool enable) noexcept {
if (channel < 8) {
const uint8_t mask = 1u << channel;
Expand Down Expand Up @@ -200,6 +212,9 @@ void FLightManager::create(const FLightManager::Builder& builder, utils::Entity
setSunAngularRadius(i, builder->mSunAngle);
setSunHaloSize(i, builder->mSunHaloSize);
setSunHaloFalloff(i, builder->mSunHaloFalloff);

setWidth(i, builder->mWidth);
setHeight(i, builder->mHeight);
}
}

Expand Down Expand Up @@ -330,6 +345,7 @@ void FLightManager::setIntensity(Instance i, float intensity, IntensityUnit unit
break;
}
case Type::SPOT:
case Type::AREA:
if (unit == IntensityUnit::LUMEN_LUX) {
// li = lp / pi
luminousIntensity = luminousPower * f::ONE_OVER_PI;
Expand Down Expand Up @@ -406,6 +422,18 @@ void FLightManager::setSunHaloFalloff(Instance i, float haloFalloff) noexcept {
}
}

void FLightManager::setWidth(Instance i, float width) noexcept {
if (i && isAreaLight(i)) {
mManager[i].width = width;
}
}

void FLightManager::setHeight(Instance i, float height) noexcept {
if (i && isAreaLight(i)) {
mManager[i].height = height;
}
}

void FLightManager::setShadowCaster(Instance i, bool shadowCaster) noexcept {
if (i) {
LightType& lightType = mManager[i].lightType;
Expand Down
22 changes: 21 additions & 1 deletion filament/src/components/LightManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,8 @@ class FLightManager : public LightManager {
UTILS_NOINLINE void setSunAngularRadius(Instance i, float angularRadius) noexcept;
UTILS_NOINLINE void setSunHaloSize(Instance i, float haloSize) noexcept;
UTILS_NOINLINE void setSunHaloFalloff(Instance i, float haloFalloff) noexcept;
UTILS_NOINLINE void setWidth(Instance i, float width) noexcept;
UTILS_NOINLINE void setHeight(Instance i, float height) noexcept;

UTILS_NOINLINE bool getLightChannel(Instance i, unsigned int channel) const noexcept;

Expand Down Expand Up @@ -152,6 +154,10 @@ class FLightManager : public LightManager {
return false; // TODO: change this when we support IES lights
}

bool isAreaLight(Instance i) const noexcept {
return getType(i) == Type::AREA;
}

bool isSunLight(Instance i) const noexcept {
return getType(i) == Type::SUN;
}
Expand Down Expand Up @@ -222,6 +228,14 @@ class FLightManager : public LightManager {
return getSpotParams(i).radius;
}

float getWidth(Instance i) const noexcept {
return mManager[i].width;
}

float getHeight(Instance i) const noexcept {
return mManager[i].height;
}

uint8_t getLightChannels(Instance i) const noexcept {
return mManager[i].channels;
}
Expand Down Expand Up @@ -250,6 +264,8 @@ class FLightManager : public LightManager {
COLOR, // color
SHADOW_PARAMS, // state needed for shadowing
SPOT_PARAMS, // state needed for spotlights
WIDTH,
HEIGHT,
SUN_ANGULAR_RADIUS, // state for the directional light sun
SUN_HALO_SIZE, // state for the directional light sun
SUN_HALO_FALLOFF, // state for the directional light sun
Expand All @@ -258,13 +274,15 @@ class FLightManager : public LightManager {
CHANNELS,
};

using Base = utils::SingleInstanceComponentManager< // 120 bytes
using Base = utils::SingleInstanceComponentManager< // 128 bytes
LightType, // 1
math::float3, // 12
math::float3, // 12
math::float3, // 12
ShadowParams, // 12
SpotParams, // 24
float,
float,
float, // 4
float, // 4
float, // 4
Expand All @@ -291,6 +309,8 @@ class FLightManager : public LightManager {
Field<COLOR> color;
Field<SHADOW_PARAMS> shadowParams;
Field<SPOT_PARAMS> spotParams;
Field<WIDTH> width;
Field<HEIGHT> height;
Field<SUN_ANGULAR_RADIUS> sunAngularRadius;
Field<SUN_HALO_SIZE> sunHaloSize;
Field<SUN_HALO_FALLOFF> sunHaloFalloff;
Expand Down
Loading

0 comments on commit e064cb8

Please sign in to comment.