From 153dc08aa7793c45afedf99c6bbfc18c6c6186d6 Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Mon, 22 May 2023 12:31:44 -0700 Subject: [PATCH] Support for custom fog-color texture Fix 282968398 --- NEW_RELEASE_NOTES.md | 1 + .../filament-android/src/main/cpp/View.cpp | 4 +- .../com/google/android/filament/View.java | 28 +++++++++-- docs/Materials.md.html | 10 ++-- filament/include/filament/Options.h | 24 +++++++++- filament/src/PerViewUniforms.cpp | 46 +++++++++++++++++-- filament/src/PerViewUniforms.h | 5 +- filament/src/details/View.cpp | 3 +- .../include/private/filament/SibStructs.h | 3 +- .../include/private/filament/UibStructs.h | 6 +-- libs/filamat/src/MaterialBuilder.cpp | 5 +- libs/filamat/src/shaders/SibGenerator.cpp | 9 ++-- libs/filamat/src/shaders/UibGenerator.cpp | 6 +-- libs/viewer/src/Settings_generated.cpp | 5 ++ shaders/src/fog.fs | 8 ++-- web/filament-js/extensions_generated.js | 1 + web/filament-js/filament.d.ts | 8 +++- web/filament-js/jsbindings_generated.cpp | 1 + 18 files changed, 143 insertions(+), 30 deletions(-) diff --git a/NEW_RELEASE_NOTES.md b/NEW_RELEASE_NOTES.md index d75f3d7ea7..a60bff8f4d 100644 --- a/NEW_RELEASE_NOTES.md +++ b/NEW_RELEASE_NOTES.md @@ -12,3 +12,4 @@ appropriate header in [RELEASE_NOTES.md](./RELEASE_NOTES.md). - engine: large-scale fog can now be opted-out on a per-renderable basis - engine: improve froxelizer resource efficiency [⚠️ **Recompile materials**] - matc: better accounting and validation of used samplers in user materials +- engine: add support for sampling fog color from a custom texture [⚠️ **Recompile materials**] diff --git a/android/filament-android/src/main/cpp/View.cpp b/android/filament-android/src/main/cpp/View.cpp index 9e353bdec6..4a230b2dcf 100644 --- a/android/filament-android/src/main/cpp/View.cpp +++ b/android/filament-android/src/main/cpp/View.cpp @@ -317,8 +317,9 @@ extern "C" JNIEXPORT void JNICALL Java_com_google_android_filament_View_nSetFogOptions(JNIEnv *, jclass , jlong nativeView, jfloat distance, jfloat maximumOpacity, jfloat height, jfloat heightFalloff, jfloat cutOffDistance, jfloat r, jfloat g, jfloat b, jfloat density, jfloat inScatteringStart, - jfloat inScatteringSize, jboolean fogColorFromIbl, jboolean enabled) { + jfloat inScatteringSize, jboolean fogColorFromIbl, jlong skyColorNativeObject, jboolean enabled) { View* view = (View*) nativeView; + Texture* skyColor = (Texture*) skyColorNativeObject; View::FogOptions options = { .distance = distance, .cutOffDistance = cutOffDistance, @@ -330,6 +331,7 @@ Java_com_google_android_filament_View_nSetFogOptions(JNIEnv *, jclass , jlong na .inScatteringStart = inScatteringStart, .inScatteringSize = inScatteringSize, .fogColorFromIbl = (bool)fogColorFromIbl, + .skyColor = skyColor, .enabled = (bool)enabled }; view->setFogOptions(options); diff --git a/android/filament-android/src/main/java/com/google/android/filament/View.java b/android/filament-android/src/main/java/com/google/android/filament/View.java index 3a2d3ef55d..ad2abc138b 100644 --- a/android/filament-android/src/main/java/com/google/android/filament/View.java +++ b/android/filament-android/src/main/java/com/google/android/filament/View.java @@ -965,7 +965,7 @@ public class View { options.heightFalloff, options.cutOffDistance, options.color[0], options.color[1], options.color[2], options.density, options.inScatteringStart, options.inScatteringSize, - options.fogColorFromIbl, + options.fogColorFromIbl, options.skyColor.getNativeObject(), options.enabled); } @@ -1203,7 +1203,7 @@ public class View { private static native void nSetSSCTOptions(long nativeView, float ssctLightConeRad, float ssctStartTraceDistance, float ssctContactDistanceMax, float ssctIntensity, float v, float v1, float v2, float ssctDepthBias, float ssctDepthSlopeBias, int ssctSampleCount, int ssctRayCount, boolean ssctEnabled); private static native void nSetBloomOptions(long nativeView, long dirtNativeObject, float dirtStrength, float strength, int resolution, float anamorphism, int levels, int blendMode, boolean threshold, boolean enabled, float highlight, boolean lensFlare, boolean starburst, float chromaticAberration, int ghostCount, float ghostSpacing, float ghostThreshold, float haloThickness, float haloRadius, float haloThreshold); - private static native void nSetFogOptions(long nativeView, float distance, float maximumOpacity, float height, float heightFalloff, float cutOffDistance, float v, float v1, float v2, float density, float inScatteringStart, float inScatteringSize, boolean fogColorFromIbl, boolean enabled); + private static native void nSetFogOptions(long nativeView, float distance, float maximumOpacity, float height, float heightFalloff, float cutOffDistance, float v, float v1, float v2, float density, float inScatteringStart, float inScatteringSize, boolean fogColorFromIbl, long skyColorNativeObject, boolean enabled); private static native void nSetBlendMode(long nativeView, int blendMode); private static native void nSetDepthOfFieldOptions(long nativeView, float cocScale, float maxApertureDiameter, boolean enabled, int filter, boolean nativeResolution, int foregroundRingCount, int backgroundRingCount, int fastGatherRingCount, int maxForegroundCOC, int maxBackgroundCOC); @@ -1518,9 +1518,31 @@ public class View { /** * The fog color will be sampled from the IBL in the view direction and tinted by `color`. * Depending on the scene this can produce very convincing results. - * This simulate a more anisotropic phase-function. + * + * This simulates a more anisotropic phase-function. + * + * `fogColorFromIbl` is ignored when skyTexture is specified. + * + * @see skyColor */ public boolean fogColorFromIbl = false; + /** + * skyTexture must be a mipmapped cubemap. When provided, the fog color will be sampled from + * this texture, higher resolution mip levels will be used for objects at the far clip plane, + * and lower resolution mip levels for objects closer to the camera. The skyTexture should + * typically be heavily blurred; a typical way to produce this texture is to blur the base + * level with a strong gaussian filter or even an irradiance filter and then generate mip + * levels as usual. How blurred the base level is somewhat of an artistic decision. + * + * This simulates a more anisotropic phase-function. + * + * `fogColorFromIbl` is ignored when skyTexture is specified. + * + * @see Texture + * @see fogColorFromIbl + */ + @Nullable + public Texture skyColor = null; /** * Enable or disable large-scale fog */ diff --git a/docs/Materials.md.html b/docs/Materials.md.html index ae8a58b35b..3a929531c1 100644 --- a/docs/Materials.md.html +++ b/docs/Materials.md.html @@ -2596,13 +2596,17 @@ pre-multiplied by default. # Sampler usage in Materials The number of usable sampler parameters (e.g.: type is `sampler2d`) in materials is limited and -depends on the material properties, shading model and feature level. +depends on the material properties, shading model, feature level and variant filter. ## Feature level 1 and 2 -`unlit` materials can use up to 13 samplers. +`unlit` materials can use up to 12 samplers by default. -`lit` materials can use up to 10 samplers by default, but if `refractionMode` or `reflectionMode` is set to `screenspace` that number becomes 9. +`lit` materials can use up to 9 samplers by default, however if `refractionMode` or `reflectionMode` +is set to `screenspace` that number is reduced to 8. + +Finally if `variantFilter` contains the `fog` filter, an extra sampler is made available, such that +`unlit` materials can use up to 13 and `lit` materials up to 10 samplers by default. ## Feature level 3 diff --git a/filament/include/filament/Options.h b/filament/include/filament/Options.h index b52d917e0d..327220bbf5 100644 --- a/filament/include/filament/Options.h +++ b/filament/include/filament/Options.h @@ -237,10 +237,32 @@ struct FogOptions { /** * The fog color will be sampled from the IBL in the view direction and tinted by `color`. * Depending on the scene this can produce very convincing results. - * This simulate a more anisotropic phase-function. + * + * This simulates a more anisotropic phase-function. + * + * `fogColorFromIbl` is ignored when skyTexture is specified. + * + * @see skyColor */ bool fogColorFromIbl = false; + /** + * skyTexture must be a mipmapped cubemap. When provided, the fog color will be sampled from + * this texture, higher resolution mip levels will be used for objects at the far clip plane, + * and lower resolution mip levels for objects closer to the camera. The skyTexture should + * typically be heavily blurred; a typical way to produce this texture is to blur the base + * level with a strong gaussian filter or even an irradiance filter and then generate mip + * levels as usual. How blurred the base level is somewhat of an artistic decision. + * + * This simulates a more anisotropic phase-function. + * + * `fogColorFromIbl` is ignored when skyTexture is specified. + * + * @see Texture + * @see fogColorFromIbl + */ + Texture* skyColor = nullptr; //!< %codegen_skip_json% %codegen_skip_javascript% + /** * Enable or disable large-scale fog */ diff --git a/filament/src/PerViewUniforms.cpp b/filament/src/PerViewUniforms.cpp index c54af51a23..9913fb2dc7 100644 --- a/filament/src/PerViewUniforms.cpp +++ b/filament/src/PerViewUniforms.cpp @@ -128,8 +128,15 @@ void PerViewUniforms::prepareTemporalNoise(FEngine& engine, s.temporalNoise = options.enabled ? temporalNoise : 0.0f; } -void PerViewUniforms::prepareFog(const CameraInfo& cameraInfo, - mat4 const& userWorldFromFog, FogOptions const& options) noexcept { +void PerViewUniforms::prepareFog(FEngine& engine, const CameraInfo& cameraInfo, + mat4 const& userWorldFromFog, FogOptions const& options, FIndirectLight const* ibl) noexcept { + + auto packHalf2x16 = [](math::half2 v) -> uint32_t { + short2 s; + memcpy(&s[0], &v[0], sizeof(s)); + return s.y << 16 | s.x; + }; + // Fog should be calculated in the "user's world coordinates" so that it's not // affected by the IBL rotation. // fogFromWorldMatrix below is only used to transform the view vector in the shader, which is @@ -152,6 +159,39 @@ void PerViewUniforms::prepareFog(const CameraInfo& cameraInfo, const float density = -float(heightFalloff * (userCameraPosition.y - options.height)); auto& s = mUniforms.edit(); + + // note: this code is written so that near/far/minLod/maxLod could be user settable + // currently they're inferred. + Handle fogColorTextureHandle; + if (options.skyColor) { + fogColorTextureHandle = downcast(options.skyColor)->getHwHandle(); + math::half2 const minMaxMip{ 0.0f, float(options.skyColor->getLevels()) - 1.0f }; + s.fogMinMaxMip = packHalf2x16(minMaxMip); + s.fogOneOverFarMinusNear = 1.0f / (cameraInfo.zf - cameraInfo.zn); + s.fogNearOverFarMinusNear = cameraInfo.zn / (cameraInfo.zf - cameraInfo.zn); + } + if (!fogColorTextureHandle && options.fogColorFromIbl) { + if (ibl) { + // When using the IBL, because we don't have mip levels, we don't have a mop to + // select based on the distance. However, we can cheat a little and use + // mip_roughnessOne-1 as the horizon base color and mip_roughnessOne as the near + // camera base color. This will give a distant fog that's a bit too sharp, but it + // improves the effect overall. + fogColorTextureHandle = ibl->getReflectionHwHandle(); + float const levelCount = float(ibl->getLevelCount()); + math::half2 const minMaxMip{ levelCount - 2.0f, levelCount - 1.0f }; + s.fogMinMaxMip = packHalf2x16(minMaxMip); + s.fogOneOverFarMinusNear = 1.0f / (cameraInfo.zf - cameraInfo.zn); + s.fogNearOverFarMinusNear = cameraInfo.zn / (cameraInfo.zf - cameraInfo.zn); + } + } + + mSamplers.setSampler(PerViewSib::FOG, { + fogColorTextureHandle ? fogColorTextureHandle : engine.getDummyCubemap()->getHwHandle(), { + .filterMag = SamplerMagFilter::LINEAR, + .filterMin = SamplerMinFilter::LINEAR_MIPMAP_LINEAR + }}); + s.fogStart = options.distance; s.fogMaxOpacity = options.maximumOpacity; s.fogHeightFalloff = heightFalloff; @@ -160,7 +200,7 @@ void PerViewUniforms::prepareFog(const CameraInfo& cameraInfo, s.fogDensity = { options.density, density, options.density * std::exp(density) }; s.fogInscatteringStart = options.inScatteringStart; s.fogInscatteringSize = options.inScatteringSize; - s.fogColorFromIbl = options.fogColorFromIbl ? 1.0f : 0.0f; + s.fogColorFromIbl = fogColorTextureHandle ? 1.0f : 0.0f; s.fogFromWorldMatrix = mat3f{ cof(fogFromWorld) }; } diff --git a/filament/src/PerViewUniforms.h b/filament/src/PerViewUniforms.h index fea74d071f..f5be309bf1 100644 --- a/filament/src/PerViewUniforms.h +++ b/filament/src/PerViewUniforms.h @@ -85,8 +85,9 @@ public: void prepareTime(FEngine& engine, math::float4 const& userTime) noexcept; void prepareTemporalNoise(FEngine& engine, TemporalAntiAliasingOptions const& options) noexcept; void prepareExposure(float ev100) noexcept; - void prepareFog(const CameraInfo& cameraInfo, - math::mat4 const& fogTransform, FogOptions const& options) noexcept; + void prepareFog(FEngine& engine, const CameraInfo& cameraInfo, + math::mat4 const& fogTransform, FogOptions const& options, + FIndirectLight const* ibl) noexcept; void prepareStructure(TextureHandle structure) noexcept; void prepareSSAO(TextureHandle ssao, AmbientOcclusionOptions const& options) noexcept; void prepareBlending(bool needsAlphaChannel) noexcept; diff --git a/filament/src/details/View.cpp b/filament/src/details/View.cpp index ffc309cfe1..3d05edf229 100644 --- a/filament/src/details/View.cpp +++ b/filament/src/details/View.cpp @@ -646,7 +646,8 @@ void FView::prepare(FEngine& engine, DriverApi& driver, ArenaScope& arena, auto const fogTransform = tcm.getWorldTransformAccurate(tcm.getInstance(mFogEntity)); mPerViewUniforms.prepareTime(engine, userTime); - mPerViewUniforms.prepareFog(cameraInfo, fogTransform, mFogOptions); + mPerViewUniforms.prepareFog(engine, cameraInfo, fogTransform, mFogOptions, + scene->getIndirectLight()); mPerViewUniforms.prepareTemporalNoise(engine, mTemporalAntiAliasingOptions); mPerViewUniforms.prepareBlending(needsAlphaChannel); mPerViewUniforms.prepareMaterialGlobals(mMaterialGlobals); diff --git a/libs/filabridge/include/private/filament/SibStructs.h b/libs/filabridge/include/private/filament/SibStructs.h index cd6f0767c8..0fb56891a4 100644 --- a/libs/filabridge/include/private/filament/SibStructs.h +++ b/libs/filabridge/include/private/filament/SibStructs.h @@ -30,8 +30,9 @@ struct PerViewSib { static constexpr size_t SSAO = 3; // variable, RGB8 {AO, [depth]} static constexpr size_t SSR = 4; // variable, RGB_11_11_10, mipmapped static constexpr size_t STRUCTURE = 5; // variable, DEPTH + static constexpr size_t FOG = 6; // variable, user defined, CUBEMAP - static constexpr size_t SAMPLER_COUNT = 6; + static constexpr size_t SAMPLER_COUNT = 7; }; struct PerRenderPrimitiveMorphingSib { diff --git a/libs/filabridge/include/private/filament/UibStructs.h b/libs/filabridge/include/private/filament/UibStructs.h index 01ad45a9c4..b8e04551fc 100644 --- a/libs/filabridge/include/private/filament/UibStructs.h +++ b/libs/filabridge/include/private/filament/UibStructs.h @@ -167,15 +167,15 @@ struct PerViewUib { // NOLINT(cppcoreguidelines-pro-type-member-init) math::float3 fogDensity; // { density, -falloff * yc, density * exp(-fallof * yc) } float fogStart; float fogMaxOpacity; - float fogReserved0; + uint32_t fogMinMaxMip; float fogHeightFalloff; float fogCutOffDistance; math::float3 fogColor; float fogColorFromIbl; float fogInscatteringStart; float fogInscatteringSize; - float fogReserved1; - float fogReserved2; + float fogOneOverFarMinusNear; + float fogNearOverFarMinusNear; std140::mat33 fogFromWorldMatrix; // -------------------------------------------------------------------------------------------- diff --git a/libs/filamat/src/MaterialBuilder.cpp b/libs/filamat/src/MaterialBuilder.cpp index 3b11d746e0..2aeedb6515 100644 --- a/libs/filamat/src/MaterialBuilder.cpp +++ b/libs/filamat/src/MaterialBuilder.cpp @@ -1238,7 +1238,7 @@ bool MaterialBuilder::checkMaterialLevelFeatures(MaterialInfo const& info) const // count how many samplers filament uses based on the material properties // note: currently SSAO is not used with unlit, but we want to keep that possibility. - uint32_t textureUsedByFilamentCount = 3; // shadowMap, structure, ssao + uint32_t textureUsedByFilamentCount = 4; // shadowMap, structure, ssao, fog texture if (info.isLit) { textureUsedByFilamentCount += 3; // froxels, dfg, specular } @@ -1246,6 +1246,9 @@ bool MaterialBuilder::checkMaterialLevelFeatures(MaterialInfo const& info) const info.refractionMode == RefractionMode::SCREEN_SPACE) { textureUsedByFilamentCount += 1; // ssr } + if (mVariantFilter & (uint32_t)UserVariantFilterBit::FOG) { + textureUsedByFilamentCount -= 1; // fog texture + } // TODO: we need constants somewhere for these values if (userSamplerCount > maxTextureCount - textureUsedByFilamentCount) { diff --git a/libs/filamat/src/shaders/SibGenerator.cpp b/libs/filamat/src/shaders/SibGenerator.cpp index 43ba0eca82..eb1a5b0f0a 100644 --- a/libs/filamat/src/shaders/SibGenerator.cpp +++ b/libs/filamat/src/shaders/SibGenerator.cpp @@ -48,7 +48,8 @@ SamplerInterfaceBlock const& SibGenerator::getPerViewSib(Variant variant) noexce { "iblSpecular", Type::SAMPLER_CUBEMAP, Format::FLOAT, Precision::MEDIUM }, { "ssao", Type::SAMPLER_2D_ARRAY, Format::FLOAT, Precision::MEDIUM }, { "ssr", Type::SAMPLER_2D_ARRAY, Format::FLOAT, Precision::MEDIUM }, - { "structure", Type::SAMPLER_2D, Format::FLOAT, Precision::HIGH }} + { "structure", Type::SAMPLER_2D, Format::FLOAT, Precision::HIGH }, + { "fog", Type::SAMPLER_CUBEMAP, Format::FLOAT, Precision::MEDIUM }} ) .build() }; @@ -60,7 +61,8 @@ SamplerInterfaceBlock const& SibGenerator::getPerViewSib(Variant variant) noexce { "iblSpecular", Type::SAMPLER_CUBEMAP, Format::FLOAT, Precision::MEDIUM }, { "ssao", Type::SAMPLER_2D_ARRAY, Format::FLOAT, Precision::MEDIUM }, { "ssr", Type::SAMPLER_2D_ARRAY, Format::FLOAT, Precision::MEDIUM }, - { "structure", Type::SAMPLER_2D, Format::FLOAT, Precision::HIGH }} + { "structure", Type::SAMPLER_2D, Format::FLOAT, Precision::HIGH }, + { "fog", Type::SAMPLER_CUBEMAP, Format::FLOAT, Precision::MEDIUM }} ) .build() }; @@ -72,7 +74,8 @@ SamplerInterfaceBlock const& SibGenerator::getPerViewSib(Variant variant) noexce { "unused2" }, { "unused3" }, { "ssr", Type::SAMPLER_2D, Format::FLOAT, Precision::MEDIUM }, - { "structure", Type::SAMPLER_2D, Format::FLOAT, Precision::HIGH }} + { "structure", Type::SAMPLER_2D, Format::FLOAT, Precision::HIGH }, + { "unused5" }} ) .build() }; diff --git a/libs/filamat/src/shaders/UibGenerator.cpp b/libs/filamat/src/shaders/UibGenerator.cpp index a5f8ba2f42..784fa938ef 100644 --- a/libs/filamat/src/shaders/UibGenerator.cpp +++ b/libs/filamat/src/shaders/UibGenerator.cpp @@ -120,15 +120,15 @@ BufferInterfaceBlock const& UibGenerator::getPerViewUib() noexcept { { "fogDensity", 0, Type::FLOAT3,Precision::HIGH, FeatureLevel::FEATURE_LEVEL_0 }, { "fogStart", 0, Type::FLOAT, Precision::HIGH, FeatureLevel::FEATURE_LEVEL_0 }, { "fogMaxOpacity", 0, Type::FLOAT, Precision::DEFAULT, FeatureLevel::FEATURE_LEVEL_0 }, - { "fogReserved0", 0, Type::FLOAT }, + { "fogMinMaxMip", 0, Type::UINT, Precision::HIGH }, { "fogHeightFalloff", 0, Type::FLOAT, Precision::HIGH, FeatureLevel::FEATURE_LEVEL_0 }, { "fogCutOffDistance", 0, Type::FLOAT, Precision::HIGH, FeatureLevel::FEATURE_LEVEL_0 }, { "fogColor", 0, Type::FLOAT3, Precision::DEFAULT, FeatureLevel::FEATURE_LEVEL_0 }, { "fogColorFromIbl", 0, Type::FLOAT, Precision::DEFAULT, FeatureLevel::FEATURE_LEVEL_0 }, { "fogInscatteringStart", 0, Type::FLOAT, Precision::HIGH, FeatureLevel::FEATURE_LEVEL_0 }, { "fogInscatteringSize", 0, Type::FLOAT, Precision::DEFAULT, FeatureLevel::FEATURE_LEVEL_0 }, - { "fogReserved1", 0, Type::FLOAT }, - { "fogReserved2", 0, Type::FLOAT }, + { "fogOneOverFarMinusNear", 0, Type::FLOAT, Precision::HIGH }, + { "fogNearOverFarMinusNear", 0, Type::FLOAT, Precision::HIGH }, { "fogFromWorldMatrix", 0, Type::MAT3, Precision::HIGH, FeatureLevel::FEATURE_LEVEL_0 }, // ------------------------------------------------------------------------------------ diff --git a/libs/viewer/src/Settings_generated.cpp b/libs/viewer/src/Settings_generated.cpp index 1e03bf2c26..2779c03fdd 100644 --- a/libs/viewer/src/Settings_generated.cpp +++ b/libs/viewer/src/Settings_generated.cpp @@ -329,6 +329,10 @@ int parse(jsmntok_t const* tokens, int i, const char* jsonChunk, FogOptions* out i = parse(tokens, i + 1, jsonChunk, &out->inScatteringSize); } else if (compare(tok, jsonChunk, "fogColorFromIbl") == 0) { i = parse(tokens, i + 1, jsonChunk, &out->fogColorFromIbl); + } else if (compare(tok, jsonChunk, "skyColor") == 0) { + // JSON serialization for skyColor is not supported. + int unused; + i = parse(tokens, i + 1, jsonChunk, &unused); } else if (compare(tok, jsonChunk, "enabled") == 0) { i = parse(tokens, i + 1, jsonChunk, &out->enabled); } else { @@ -355,6 +359,7 @@ std::ostream& operator<<(std::ostream& out, const FogOptions& in) { << "\"inScatteringStart\": " << (in.inScatteringStart) << ",\n" << "\"inScatteringSize\": " << (in.inScatteringSize) << ",\n" << "\"fogColorFromIbl\": " << to_string(in.fogColorFromIbl) << ",\n" + // JSON serialization for skyColor is not supported. << "\"enabled\": " << to_string(in.enabled) << "\n" << "}"; } diff --git a/shaders/src/fog.fs b/shaders/src/fog.fs index 621358dbfc..98d5ae928c 100644 --- a/shaders/src/fog.fs +++ b/shaders/src/fog.fs @@ -42,15 +42,15 @@ vec4 fog(vec4 color, highp vec3 view) { #if MATERIAL_FEATURE_LEVEL > 0 if (frameUniforms.fogColorFromIbl > 0.0) { - // get fog color from envmap - // TODO: use a lower resolution mip as we get further (problem we don't have mips!) - float lod = frameUniforms.iblRoughnessOneLevel; + float normalizedDepth = d * frameUniforms.fogOneOverFarMinusNear - frameUniforms.fogNearOverFarMinusNear; + lowp vec2 minMaxMip = unpackHalf2x16(frameUniforms.fogMinMaxMip); + lowp float lod = mix(minMaxMip.y, minMaxMip.x, saturate(normalizedDepth)); // when sampling the IBL we need to take into account the IBL transform. We know it's a // a rigid transform, so we can take the transpose instead of the inverse, and for the // same reason we can use it directly instead of taking the cof() to transfrom a vector. highp mat3 worldFromUserWorldMatrix = transpose(mat3(frameUniforms.userWorldFromWorldMatrix)); - fogColor *= textureLod(light_iblSpecular, worldFromUserWorldMatrix * view, lod).rgb; + fogColor *= textureLod(light_fog, worldFromUserWorldMatrix * view, lod).rgb; } #endif diff --git a/web/filament-js/extensions_generated.js b/web/filament-js/extensions_generated.js index ecaea09a36..48ad68e6f9 100644 --- a/web/filament-js/extensions_generated.js +++ b/web/filament-js/extensions_generated.js @@ -51,6 +51,7 @@ Filament.loadGeneratedExtensions = function() { inScatteringStart: 0.0, inScatteringSize: -1.0, fogColorFromIbl: false, + // JavaScript binding for skyColor is not yet supported, must use default value. enabled: false, }; return Object.assign(options, overrides); diff --git a/web/filament-js/filament.d.ts b/web/filament-js/filament.d.ts index 5688822101..bd6a4d8d9a 100644 --- a/web/filament-js/filament.d.ts +++ b/web/filament-js/filament.d.ts @@ -1364,9 +1364,15 @@ export interface View$FogOptions { /** * The fog color will be sampled from the IBL in the view direction and tinted by `color`. * Depending on the scene this can produce very convincing results. - * This simulate a more anisotropic phase-function. + * + * This simulates a more anisotropic phase-function. + * + * `fogColorFromIbl` is ignored when skyTexture is specified. + * + * @see skyColor */ fogColorFromIbl?: boolean; + // JavaScript binding for skyColor is not yet supported, must use default value. /** * Enable or disable large-scale fog */ diff --git a/web/filament-js/jsbindings_generated.cpp b/web/filament-js/jsbindings_generated.cpp index 5144da712d..67012fa620 100644 --- a/web/filament-js/jsbindings_generated.cpp +++ b/web/filament-js/jsbindings_generated.cpp @@ -52,6 +52,7 @@ value_object("View$FogOptions") .field("inScatteringStart", &View::FogOptions::inScatteringStart) .field("inScatteringSize", &View::FogOptions::inScatteringSize) .field("fogColorFromIbl", &View::FogOptions::fogColorFromIbl) + // JavaScript binding for skyColor is not yet supported, must use default value. .field("enabled", &View::FogOptions::enabled) ;