Skip to content

Commit

Permalink
Support for custom fog-color texture
Browse files Browse the repository at this point in the history
Fix 282968398
  • Loading branch information
pixelflinger committed May 23, 2023
1 parent 332b924 commit 153dc08
Show file tree
Hide file tree
Showing 18 changed files with 143 additions and 30 deletions.
1 change: 1 addition & 0 deletions NEW_RELEASE_NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -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**]
4 changes: 3 additions & 1 deletion android/filament-android/src/main/cpp/View.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -965,7 +965,7 @@ public void setFogOptions(@NonNull FogOptions options) {
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);
}

Expand Down Expand Up @@ -1203,7 +1203,7 @@ void clearNativeObject() {
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);
Expand Down Expand Up @@ -1518,9 +1518,31 @@ public static class 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
*/
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
*/
Expand Down
10 changes: 7 additions & 3 deletions docs/Materials.md.html
Original file line number Diff line number Diff line change
Expand Up @@ -2596,13 +2596,17 @@
# 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

Expand Down
24 changes: 23 additions & 1 deletion filament/include/filament/Options.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
*/
Expand Down
46 changes: 43 additions & 3 deletions filament/src/PerViewUniforms.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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<HwTexture> 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;
Expand All @@ -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) };
}

Expand Down
5 changes: 3 additions & 2 deletions filament/src/PerViewUniforms.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,9 @@ class PerViewUniforms {
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;
Expand Down
3 changes: 2 additions & 1 deletion filament/src/details/View.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
3 changes: 2 additions & 1 deletion libs/filabridge/include/private/filament/SibStructs.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
6 changes: 3 additions & 3 deletions libs/filabridge/include/private/filament/UibStructs.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

// --------------------------------------------------------------------------------------------
Expand Down
5 changes: 4 additions & 1 deletion libs/filamat/src/MaterialBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1238,14 +1238,17 @@ 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
}
if (info.reflectionMode == ReflectionMode::SCREEN_SPACE ||
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) {
Expand Down
9 changes: 6 additions & 3 deletions libs/filamat/src/shaders/SibGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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() };

Expand All @@ -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() };

Expand All @@ -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() };

Expand Down
6 changes: 3 additions & 3 deletions libs/filamat/src/shaders/UibGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 },

// ------------------------------------------------------------------------------------
Expand Down
5 changes: 5 additions & 0 deletions libs/viewer/src/Settings_generated.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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"
<< "}";
}
Expand Down
Loading

0 comments on commit 153dc08

Please sign in to comment.