Skip to content

Commit

Permalink
add support for custom fog color in gltf_viewer
Browse files Browse the repository at this point in the history
this is implemented by here by using the skybox texture and blurring it
with the irradiance filter + mipmapping. This only creates a subtle
anisotropic phase-function effect.
  • Loading branch information
pixelflinger committed May 24, 2023
1 parent 2806221 commit a8afa91
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 1 deletion.
5 changes: 5 additions & 0 deletions libs/filamentapp/include/filamentapp/IBL.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ class IBL {
return mSkybox;
}

filament::Texture* getFogTexture() const noexcept {
return mFogTexture;
}

bool hasSphericalHarmonics() const { return mHasSphericalHarmonics; }
filament::math::float3 const* getSphericalHarmonics() const { return mBands; }

Expand All @@ -77,6 +81,7 @@ class IBL {
filament::Texture* mTexture = nullptr;
filament::IndirectLight* mIndirectLight = nullptr;
filament::Texture* mSkyboxTexture = nullptr;
filament::Texture* mFogTexture = nullptr;
filament::Skybox* mSkybox = nullptr;
};

Expand Down
14 changes: 14 additions & 0 deletions libs/filamentapp/src/IBL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ IBL::~IBL() {
mEngine.destroy(mTexture);
mEngine.destroy(mSkybox);
mEngine.destroy(mSkyboxTexture);
mEngine.destroy(mFogTexture);
}

bool IBL::loadFromEquirect(Path const& path) {
Expand Down Expand Up @@ -93,13 +94,17 @@ bool IBL::loadFromEquirect(Path const& path) {
IBLPrefilterContext context(mEngine);
IBLPrefilterContext::EquirectangularToCubemap equirectangularToCubemap(context);
IBLPrefilterContext::SpecularFilter specularFilter(context);
IBLPrefilterContext::IrradianceFilter irradianceFilter(context);

mSkyboxTexture = equirectangularToCubemap(equirect);

mEngine.destroy(equirect);

mTexture = specularFilter(mSkyboxTexture);

mFogTexture = irradianceFilter({ .generateMipmap=false }, mSkyboxTexture);
mFogTexture->generateMipmaps(mEngine);

mIndirectLight = IndirectLight::Builder()
.reflections(mTexture)
.intensity(IBL_INTENSITY)
Expand Down Expand Up @@ -136,6 +141,15 @@ bool IBL::loadFromKtx(const std::string& prefix) {
mSkyboxTexture = Ktx1Reader::createTexture(&mEngine, skyKtx, false);
mTexture = Ktx1Reader::createTexture(&mEngine, iblKtx, false);

// TODO: create the fog texture, it's a bit complicated because IBLPrefilter requires
// the source image to have miplevels, and it's not guaranteed here and also
// not guaranteed we can generate them (e.g. texture could be compressed)
//IBLPrefilterContext context(mEngine);
//IBLPrefilterContext::IrradianceFilter irradianceFilter(context);
//mFogTexture = irradianceFilter({ .generateMipmap=false }, mSkyboxTexture);
//mFogTexture->generateMipmaps(mEngine);


if (!iblKtx->getSphericalHarmonics(mBands)) {
return false;
}
Expand Down
5 changes: 5 additions & 0 deletions libs/viewer/include/viewer/Settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,10 @@ struct DynamicLightingSettings {
float zLightFar = 100;
};

struct FogSettings {
Texture* fogColorTexture = nullptr;
};

// This defines fields in the same order as the setter methods in filament::View.
struct ViewSettings {
// standalone View settings
Expand All @@ -185,6 +189,7 @@ struct ViewSettings {
// Custom View Options
ColorGradingSettings colorGrading;
DynamicLightingSettings dynamicLighting;
FogSettings fogSettings;
};

template <typename T>
Expand Down
23 changes: 22 additions & 1 deletion libs/viewer/src/ViewerGui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -889,6 +889,13 @@ void ViewerGui::updateUserInterface() {
}

if (ImGui::CollapsingHeader("Fog")) {
int fogColorSource = 0;
if (mSettings.view.fog.skyColor) {
fogColorSource = 2;
} else if (mSettings.view.fog.fogColorFromIbl) {
fogColorSource = 1;
}

bool excludeSkybox = !std::isinf(mSettings.view.fog.cutOffDistance);
ImGui::Indent();
ImGui::Checkbox("Enable large-scale fog", &mSettings.view.fog.enabled);
Expand All @@ -899,11 +906,25 @@ void ViewerGui::updateUserInterface() {
ImGui::SliderFloat("Sun Scattering start [m]", &mSettings.view.fog.inScatteringStart, 0.0f, 100.0f);
ImGui::SliderFloat("Sun Scattering size", &mSettings.view.fog.inScatteringSize, 0.1f, 100.0f);
ImGui::Checkbox("Exclude Skybox", &excludeSkybox);
ImGui::Checkbox("Color from IBL", &mSettings.view.fog.fogColorFromIbl);
ImGui::Combo("Color##fogColor", &fogColorSource, "Constant\0IBL\0Skybox\0\0");
ImGui::ColorPicker3("Color", mSettings.view.fog.color.v);
ImGui::Unindent();
mSettings.view.fog.cutOffDistance =
excludeSkybox ? 1e6f : std::numeric_limits<float>::infinity();
switch (fogColorSource) {
case 0:
mSettings.view.fog.skyColor = nullptr;
mSettings.view.fog.fogColorFromIbl = false;
break;
case 1:
mSettings.view.fog.skyColor = nullptr;
mSettings.view.fog.fogColorFromIbl = true;
break;
case 2:
mSettings.view.fog.skyColor = mSettings.view.fogSettings.fogColorTexture;
mSettings.view.fog.fogColorFromIbl = false;
break;
}
}

if (ImGui::CollapsingHeader("Scene")) {
Expand Down
1 change: 1 addition & 0 deletions samples/gltf_viewer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -573,6 +573,7 @@ int main(int argc, char** argv) {
auto ibl = FilamentApp::get().getIBL();
if (ibl) {
app.viewer->setIndirectLight(ibl->getIndirectLight(), ibl->getSphericalHarmonics());
app.viewer->getSettings().view.fogSettings.fogColorTexture = ibl->getFogTexture();
}
};

Expand Down

0 comments on commit a8afa91

Please sign in to comment.