Compare commits

..

15 Commits

Author SHA1 Message Date
Benjamin Doherty
18dab53920 All changes 2022-11-14 22:20:59 -08:00
Benjamin Doherty
b754b81e6f Almost all the changes 2022-11-14 22:16:58 -08:00
Benjamin Doherty
65bb66f90c Even more shader changes 2022-11-14 22:00:10 -08:00
Benjamin Doherty
a0af84d034 Some more shader changes 2022-11-14 21:56:50 -08:00
Benjamin Doherty
3cdaf3feeb ShadowMapManager.h changes 2022-11-14 17:18:00 -08:00
Benjamin Doherty
da7d1b6fa9 Update Scene.cpp 2022-11-14 17:09:55 -08:00
Benjamin Doherty
3129226839 Fix literal 0 2022-11-14 17:07:55 -08:00
Benjamin Doherty
6935acafff Changes to ShadowMapManager 2022-11-14 17:07:25 -08:00
Benjamin Doherty
d8103f4fd6 Update ShaderGenerator.cpp 2022-11-14 16:55:50 -08:00
Benjamin Doherty
09a13f4015 Some shadowing changes 2022-11-14 15:25:08 -08:00
Benjamin Doherty
e888023102 Some shader changes 2022-11-14 15:00:09 -08:00
Benjamin Doherty
f62f4736f0 Adjust LightsUib 2022-11-14 13:39:08 -08:00
Benjamin Doherty
a378272d56 Remove some more uniforms 2022-11-14 13:34:26 -08:00
Benjamin Doherty
3d61938fcf Remove lightFromWorldMatrix from PerViewUniforms 2022-11-14 13:30:54 -08:00
Benjamin Doherty
a9f3937da6 Trivial changes 2022-11-14 13:05:52 -08:00
18 changed files with 178 additions and 133 deletions

View File

@@ -31,7 +31,7 @@ repositories {
}
dependencies {
implementation 'com.google.android.filament:filament-android:1.29.0'
implementation 'com.google.android.filament:filament-android:1.28.2'
}
```
@@ -51,7 +51,7 @@ Here are all the libraries available in the group `com.google.android.filament`:
iOS projects can use CocoaPods to install the latest release:
```
pod 'Filament', '~> 1.29.0'
pod 'Filament', '~> 1.28.2'
```
### Snapshots

View File

@@ -5,8 +5,6 @@ A new header is inserted each time a *tag* is created.
## main branch
## v1.29.0
- gltfio: calculate primitive's AABB correctly.
- gltfio: recompute bounding boxes with morph targets
- engine: add missing getters on `MaterialInstance`

View File

@@ -1,5 +1,5 @@
GROUP=com.google.android.filament
VERSION_NAME=1.29.0
VERSION_NAME=1.28.2
POM_DESCRIPTION=Real-time physically based rendering engine for Android.

View File

@@ -750,11 +750,6 @@ void RenderPass::Executor::execute(backend::DriverApi& driver,
continue;
}
// primitiveHandle may be invalid if no geometry was set on the renderable.
if (UTILS_UNLIKELY(!first->primitive.primitiveHandle)) {
continue;
}
// per-renderable uniform
const PrimitiveInfo info = first->primitive;
pipeline.rasterState = info.rasterState;

View File

@@ -413,10 +413,41 @@ ShadowMap::ShaderParameters ShadowMap::updateDirectional(FEngine& engine,
return shaderParameters;
}
ShadowMap::ShaderParameters ShadowMap::updateSpotOrPoint(
mat4f const& Mv, float outerConeAngle, float nearPlane, float farPlane,
const ShadowMapInfo& shadowMapInfo, const FLightManager::ShadowParams& params) noexcept {
const mat4f Mp = mat4f::perspective(outerConeAngle * f::RAD_TO_DEG * 2.0f, 1.0f, nearPlane, farPlane);
ShadowMap::ShaderParameters ShadowMap::updateSpot(FEngine& engine,
const FScene::LightSoa& lightData, size_t index,
filament::CameraInfo const& camera,
const ShadowMapInfo& shadowMapInfo,
FScene const& scene, SceneInfo sceneInfo) noexcept {
ShaderParameters shaderParameters;
auto& lcm = engine.getLightManager();
auto li = lightData.elementAt<FScene::LIGHT_INSTANCE>(index);
auto position = lightData.elementAt<FScene::POSITION_RADIUS>(index).xyz;
auto direction = lightData.elementAt<FScene::DIRECTION>(index);
auto radius = lightData.elementAt<FScene::POSITION_RADIUS>(index).w;
auto outerConeAngle = lcm.getSpotLightOuterCone(li);
const FLightManager::ShadowParams& params = lcm.getShadowParams(li);
/*
* Compute the light model matrix.
*/
// Choose a reasonable value for the near plane.
const mat4f Mv = getDirectionalLightViewMatrix(direction, position);
// find decent near/far
ShadowMap::updateSceneInfoSpot(Mv, scene, sceneInfo);
// if the scene was empty, near > far
mHasVisibleShadows = -sceneInfo.lsNearFar[0] < -sceneInfo.lsNearFar[1];
// FIXME: we need a configuration for minimum near plane (for now hardcoded to 1cm)
float nearPlane = std::max(0.01f, -sceneInfo.lsNearFar[0]);
float farPlane = std::min(radius, -sceneInfo.lsNearFar[1]);
float outerConeAngleDegrees = outerConeAngle * f::RAD_TO_DEG;
const mat4f Mp = mat4f::perspective(outerConeAngleDegrees * 2.0f, 1.0f, nearPlane, farPlane);
const mat4f MpMv(math::highPrecisionMultiply(Mp, Mv));
// Final shadow transform
@@ -438,9 +469,7 @@ ShadowMap::ShaderParameters ShadowMap::updateSpotOrPoint(
// = zInLightSpace * texelSizeAtOneMeter
// = zInLightSpace * (2*tan(halfConeAngle)/dimension)
// Note: this would not work with LISPSM, which warps the texture space.
ShaderParameters shaderParameters;
shaderParameters.texelSizeAtOneMeterWs =
(2.0f * std::tan(outerConeAngle) / float(shadowMapInfo.shadowDimension));
shaderParameters.texelSizeAtOneMeterWs = (2.0f * std::tan(outerConeAngle) / float(shadowMapInfo.shadowDimension));
shaderParameters.lightFromWorldZ = -transpose(Mv)[2]; // negate because camera looks in -Z
if (!shadowMapInfo.vsm) {
@@ -449,7 +478,78 @@ ShadowMap::ShaderParameters ShadowMap::updateSpotOrPoint(
shaderParameters.lightSpace = computeVsmLightSpaceMatrix(St, Mv, nearPlane, farPlane);
}
const float constantBias = shadowMapInfo.vsm ? 0.0f : params.options.constantBias;
const mat4f b = mat4f::translation(direction * constantBias);
const mat4f Sb = S * b;
// It's important to set the light camera's model matrix separately from its projection, so that
// the cameraPosition uniform gets set correctly.
// mLightSpace is used in the shader to access the shadow map texture, and has the model matrix
// baked in.
// The model matrix below is in fact inverted to get the view matrix and passed to the
// shader as 'viewFromWorldMatrix', and is used in the VSM case to compute the depth metric.
// (see depth_main.fs). Note that in the case of VSM, 'b' below is identity.
mCamera->setModelMatrix(mat4{ FCamera::rigidTransformInverse(Mv * b) });
mCamera->setCustomProjection(mat4(Mp), nearPlane, farPlane);
// for the debug camera, we need to undo the world origin
mDebugCamera->setCustomProjection(mat4(Sb * camera.worldOrigin), nearPlane, radius);
return shaderParameters;
}
ShadowMap::ShaderParameters ShadowMap::updatePoint(FEngine& engine,
const FScene::LightSoa& lightData, size_t index,
filament::CameraInfo const& camera, const ShadowMapInfo& shadowMapInfo, FScene const& scene,
SceneInfo, uint8_t face) noexcept {
ShaderParameters shaderParameters;
// check if this shadow map has anything to render
mHasVisibleShadows = false;
FScene::RenderableSoa const& UTILS_RESTRICT soa = scene.getRenderableData();
auto const* const UTILS_RESTRICT visibleMasks = soa.data<FScene::VISIBLE_MASK>();
size_t c = soa.size();
for (size_t i = 0; i < c; i++) {
if (visibleMasks[i] & VISIBLE_DYN_SHADOW_RENDERABLE) {
mHasVisibleShadows = true;
break;
}
}
if (!mHasVisibleShadows) {
return shaderParameters;
}
auto& lcm = engine.getLightManager();
auto li = lightData.elementAt<FScene::LIGHT_INSTANCE>(index);
auto position = lightData.elementAt<FScene::POSITION_RADIUS>(index).xyz;
auto radius = lightData.elementAt<FScene::POSITION_RADIUS>(index).w;
const FLightManager::ShadowParams& params = lcm.getShadowParams(li);
/*
* Compute the light model matrix.
*/
const mat4f Mv = getPointLightViewMatrix(TextureCubemapFace(face), position);
const float3 direction = -transpose(Mv)[2].xyz;
// TODO: don't hardcode near plane
// Choose a reasonable value for the near plane.
float nearPlane = 0.01f;
float farPlane = radius;
const mat4f Mp = mat4f::perspective(90.0f, 1.0f, nearPlane, farPlane);
// For calculating the point light normal bias, we need the texel size in world space at the
// sample location. Using Thales's theorem, we find:
// texelSize(zInLightSpace) = zInLightSpace * texelSizeOnTheNearPlane / near
// = zInLightSpace * texelSizeAtOneMeter
// = zInLightSpace * (2*tan(halfConeAngle)/dimension)
// Note: this would not work with LISPSM, which warps the texture space.
shaderParameters.texelSizeAtOneMeterWs =
(2.0f * std::tan(f::PI_4) / float(shadowMapInfo.shadowDimension));
const float constantBias = shadowMapInfo.vsm ? 0.0f : params.options.constantBias;
const mat4f b = mat4f::translation(direction * constantBias);
@@ -467,65 +567,6 @@ ShadowMap::ShaderParameters ShadowMap::updateSpotOrPoint(
return shaderParameters;
}
ShadowMap::ShaderParameters ShadowMap::updateSpot(FEngine& engine,
const FScene::LightSoa& lightData, size_t index,
filament::CameraInfo const& camera,
const ShadowMapInfo& shadowMapInfo,
FScene const& scene, SceneInfo sceneInfo) noexcept {
auto& lcm = engine.getLightManager();
auto position = lightData.elementAt<FScene::POSITION_RADIUS>(index).xyz;
auto direction = lightData.elementAt<FScene::DIRECTION>(index);
auto radius = lightData.elementAt<FScene::POSITION_RADIUS>(index).w;
auto li = lightData.elementAt<FScene::LIGHT_INSTANCE>(index);
const FLightManager::ShadowParams& params = lcm.getShadowParams(li);
const mat4f Mv = getDirectionalLightViewMatrix(direction, position);
// find decent near/far
ShadowMap::updateSceneInfoSpot(Mv, scene, sceneInfo);
// if the scene was empty, near > far
mHasVisibleShadows = -sceneInfo.lsNearFar[0] < -sceneInfo.lsNearFar[1];
if (!mHasVisibleShadows) {
return {};
}
// FIXME: we need a configuration for minimum near plane (for now hardcoded to 1cm)
float nearPlane = std::max(0.01f, -sceneInfo.lsNearFar[0]);
float farPlane = std::min(radius, -sceneInfo.lsNearFar[1]);
auto outerConeAngle = lcm.getSpotLightOuterCone(li);
return updateSpotOrPoint(Mv, outerConeAngle, nearPlane, farPlane, shadowMapInfo, params);
}
ShadowMap::ShaderParameters ShadowMap::updatePoint(FEngine& engine,
const FScene::LightSoa& lightData, size_t index,
filament::CameraInfo const& camera, const ShadowMapInfo& shadowMapInfo, FScene const& scene,
SceneInfo, uint8_t face) noexcept {
// check if this shadow map has anything to render
mHasVisibleShadows = false;
FScene::RenderableSoa const& UTILS_RESTRICT soa = scene.getRenderableData();
auto const* const UTILS_RESTRICT visibleMasks = soa.data<FScene::VISIBLE_MASK>();
size_t c = soa.size();
for (size_t i = 0; i < c; i++) {
if (visibleMasks[i] & VISIBLE_DYN_SHADOW_RENDERABLE) {
mHasVisibleShadows = true;
break;
}
}
if (!mHasVisibleShadows) {
return {};
}
auto& lcm = engine.getLightManager();
auto position = lightData.elementAt<FScene::POSITION_RADIUS>(index).xyz;
auto radius = lightData.elementAt<FScene::POSITION_RADIUS>(index).w;
auto li = lightData.elementAt<FScene::LIGHT_INSTANCE>(index);
const FLightManager::ShadowParams& params = lcm.getShadowParams(li);
const mat4f Mv = getPointLightViewMatrix(TextureCubemapFace(face), position);
return updateSpotOrPoint(Mv, 45.0f * f::DEG_TO_RAD, 0.01f, radius, shadowMapInfo, params);
}
mat4f ShadowMap::applyLISPSM(mat4f& Wp,
filament::CameraInfo const& camera, FLightManager::ShadowParams const& params,
mat4f const& LMpMv,

View File

@@ -214,11 +214,6 @@ private:
// 8 corners, 12 segments w/ 2 intersection max -- all of this twice (8 + 12 * 2) * 2 (768 bytes)
using FrustumBoxIntersection = std::array<math::float3, 64>;
ShaderParameters updateSpotOrPoint(
math::mat4f const& Mv, float outerConeAngle, float nearPlane, float farPlane,
const ShadowMapInfo& shadowMapInfo,
const FLightManager::ShadowParams& params) noexcept;
static math::mat4f applyLISPSM(math::mat4f& Wp,
filament::CameraInfo const& camera, FLightManager::ShadowParams const& params,
const math::mat4f& LMpMv,

View File

@@ -690,7 +690,7 @@ void ShadowMapManager::prepareSpotShadowMap(ShadowMap& shadowMap,
s.shadows[shadowIndex].elvsm = options->vsm.elvsm;
s.shadows[shadowIndex].bulbRadiusLs =
mSoftShadowOptions.penumbraScale * options->shadowBulbRadius
/ wsTexelSizeAtOneMeter;
/ wsTexelSizeAtOneMeter;
}
}
@@ -763,10 +763,15 @@ void ShadowMapManager::preparePointShadowMap(ShadowMap& shadowMap,
const double n = shadowMap.getCamera().getNear();
const double f = shadowMap.getCamera().getCullingFar();
s.shadows[shadowIndex].layer = shadowMap.getLayer();
s.shadows[shadowIndex].lightFromWorldMatrix = shaderParameters.lightSpace;
s.shadows[shadowIndex].lightFromWorldMatrix = {}; // no texture matrix for point lights
s.shadows[shadowIndex].direction = {}; // no direction of point lights
s.shadows[shadowIndex].normalBias = normalBias * wsTexelSizeAtOneMeter;
s.shadows[shadowIndex].lightFromWorldZ = shaderParameters.lightFromWorldZ;
s.shadows[shadowIndex].lightFromWorldZ = {
-((n + f) / (f - n)) * 0.5f + 0.5f,
(f * n) / (f - n),
-n / (f - n),
1.0f / (f - n),
};
s.shadows[shadowIndex].texelSizeAtOneMeter = wsTexelSizeAtOneMeter;
s.shadows[shadowIndex].nearOverFarMinusNear = float(n / (f - n));
s.shadows[shadowIndex].elvsm = options->vsm.elvsm;

View File

@@ -442,15 +442,9 @@ Program FMaterial::getProgramBuilderWithVariants(
}
}
int platformId = 0;
#if defined(IOS)
platformId = 1;
#endif
program.specializationConstants({
{ 0, (int)mEngine.getSupportedFeatureLevel() },
{ 1, (int)CONFIG_MAX_INSTANCES },
{ 2, platformId }
{ 1, (int)CONFIG_MAX_INSTANCES }
});
return program;

View File

@@ -1,12 +1,12 @@
Pod::Spec.new do |spec|
spec.name = "Filament"
spec.version = "1.29.0"
spec.version = "1.28.2"
spec.license = { :type => "Apache 2.0", :file => "LICENSE" }
spec.homepage = "https://google.github.io/filament"
spec.authors = "Google LLC."
spec.summary = "Filament is a real-time physically based rendering engine for Android, iOS, Windows, Linux, macOS, and WASM/WebGL."
spec.platform = :ios, "11.0"
spec.source = { :http => "https://github.com/google/filament/releases/download/v1.29.0/filament-v1.29.0-ios.tgz" }
spec.source = { :http => "https://github.com/google/filament/releases/download/v1.28.2/filament-v1.28.2-ios.tgz" }
# Fix linking error with Xcode 12; we do not yet support the simulator on Apple silicon.
spec.pod_target_xcconfig = {

View File

@@ -247,10 +247,10 @@ static_assert(sizeof(LightsUib) == 64,
struct ShadowUib { // NOLINT(cppcoreguidelines-pro-type-member-init)
static constexpr std::string_view _name{ "ShadowUniforms" };
struct alignas(16) ShadowData {
math::mat4f lightFromWorldMatrix; // 64
math::float3 direction; // 12
float normalBias; // 4
math::float4 lightFromWorldZ; // 16
math::mat4f lightFromWorldMatrix; // 64 - unused for point lights
math::float3 direction; // 12 - unused for point lights
float normalBias; // 4 - unused for point lights
math::float4 lightFromWorldZ; // 16 - point lights { depth reconstruction values }
float texelSizeAtOneMeter; // 4
float bulbRadiusLs; // 4

View File

@@ -35,11 +35,6 @@ Variant Variant::filterUserVariant(
if (filterMask & (uint32_t)UserVariantFilterBit::FOG) {
variant.key &= ~(filterMask & FOG);
}
} else {
// depth variants can have their VSM bit filtered
if (filterMask & (uint32_t)UserVariantFilterBit::VSM) {
variant.key &= ~(filterMask & VSM);
}
}
if (!isSSRVariant(variant)) {
// SSR variant needs to be handled separately
@@ -58,6 +53,8 @@ Variant Variant::filterUserVariant(
return variant;
}
namespace details {
// compile time sanity-check tests

View File

@@ -123,7 +123,6 @@ utils::io::sstream& CodeGenerator::generateProlog(utils::io::sstream& out, Shade
out << '\n';
generateSpecificationConstant(out, "BACKEND_FEATURE_LEVEL", 0, 1);
generateSpecificationConstant(out, "CONFIG_MAX_INSTANCES", 1, (int)CONFIG_MAX_INSTANCES);
generateSpecificationConstant(out, "TARGET_PLATFORM", 2, 0);
out << '\n';
out << SHADERS_COMMON_DEFINES_GLSL_DATA;

View File

@@ -22,11 +22,3 @@
#define float3x3 mat3
#define float4x4 mat4
#define TARGET_PLATFORM_UNKNOWN 0
#define TARGET_PLATFORM_IOS 1
#if defined(TARGET_GLES_ENVIRONMENT)
const bool openGlesIos = TARGET_PLATFORM == TARGET_PLATFORM_IOS;
#else
const bool openGlesIos = false;
#endif

View File

@@ -128,7 +128,7 @@ highp vec4 getCascadeLightSpacePosition(uint cascade) {
// For the first cascade, return the interpolated light space position.
// This branch will be coherent (mostly) for neighboring fragments, and it's worth avoiding
// the matrix multiply inside computeLightSpacePosition.
if (cascade == 0u && !openGlesIos) {
if (cascade == 0u) {
// Note: this branch may cause issues with derivatives
return vertex_lightSpacePosition;
}

View File

@@ -211,15 +211,18 @@ void evaluatePunctualLights(const MaterialInputs material,
if (light.NoL > 0.0) {
if (light.castsShadows) {
uint shadowIndex = light.shadowIndex;
highp vec4 shadowPosition;
if (light.type == LIGHT_TYPE_POINT) {
// point-light shadows are sampled from a direction
highp vec3 r = getWorldPosition() - light.worldPosition;
uint face = getPointLightFace(r);
highp uint face = 0u;
// getShadowPosition returns zLight which is needed for PCSS/DPCF
shadowPosition = getShadowPosition(r, shadowIndex, light.zLight, face);
shadowIndex += face;
light.zLight = dot(shadowUniforms.shadows[shadowIndex].lightFromWorldZ,
vec4(getWorldPosition(), 1.0));
} else {
// getShadowPosition needs zLight for applying the normal bias
shadowPosition = getShadowPosition(false, shadowIndex, 0u, light.zLight);
}
highp vec4 shadowPosition = getShadowPosition(false, shadowIndex, 0u, light.zLight);
visibility = shadow(false, light_shadowMap, shadowIndex,
shadowPosition, light.zLight);
}

View File

@@ -141,16 +141,11 @@ void main() {
#endif
#if defined(VARIANT_HAS_SHADOWING) && defined(VARIANT_HAS_DIRECTIONAL_LIGHTING)
if (openGlesIos) {
// Hack for OpenGL ES on iOS.
vertex_lightSpacePosition = vec4(1.0);
} else {
vertex_lightSpacePosition = computeLightSpacePosition(
vertex_worldPosition.xyz, vertex_worldNormal,
frameUniforms.lightDirection,
shadowUniforms.shadows[0].normalBias,
shadowUniforms.shadows[0].lightFromWorldMatrix);
}
vertex_lightSpacePosition = computeLightSpacePosition(
vertex_worldPosition.xyz, vertex_worldNormal,
frameUniforms.lightDirection,
shadowUniforms.shadows[0].normalBias,
shadowUniforms.shadows[0].lightFromWorldMatrix);
#endif
#endif // !defined(USE_OPTIMIZED_DEPTH_VERTEX_SHADER)

View File

@@ -494,20 +494,51 @@ highp vec4 getShadowPosition(const bool DIRECTIONAL,
return p;
}
uint getPointLightFace(const highp vec3 r) {
// get {texture coordinate, layer} for point shadow maps
highp vec4 getShadowPosition(const highp vec3 r, const highp uint shadowIndex,
out highp float d, out highp uint face) {
highp vec4 tc;
highp float rx = abs(r.x);
highp float ry = abs(r.y);
highp float rz = abs(r.z);
highp float d = max(rx, max(ry, rz));
d = max(rx, max(ry, rz));
highp float ma = 1.0 / d;
if (d == rx) {
return (r.x >= 0.0 ? 0u : 1u);
tc.x = r.x >= 0.0 ? r.z : -r.z;
tc.y = r.y;
face = (r.x >= 0.0 ? 0u : 1u);
} else if (d == ry) {
return (r.y >= 0.0 ? 2u : 3u);
tc.x = r.y >= 0.0 ? r.x : -r.x;
tc.y = r.z;
face = (r.y >= 0.0 ? 2u : 3u);
} else {
return (r.z >= 0.0 ? 4u : 5u);
tc.x = r.z >= 0.0 ? -r.x : r.x;
tc.y = r.y;
face = (r.z >= 0.0 ? 4u : 5u);
}
// ma is guaranteed to be >= sc and tc
tc.xy = (tc.xy * ma + vec2(1.0)) * 0.5;
highp vec4 nf = shadowUniforms.shadows[shadowIndex + face].lightFromWorldZ;
// z coordinate of the normalized fragment position in light-space
// i.e.: remap [near, far] to [0,1] : d = (d - n) / (f - n)
d = nf[2] + nf[3] * d;
if (frameUniforms.shadowSamplingType == SHADOW_SAMPLING_RUNTIME_EVSM) {
// for VSM, the depth metric is linear normalized in light-space
tc.z = d;
} else {
// for other types of shadows it's clip-space depth. Below is an optimized version of
// (lightProjection * position).z
tc.z = nf[0] + nf[1] * ma;
}
// FIXME: the normal bias is not applied
tc.w = 1.0;
return tc;
}
// PCF sampling

View File

@@ -1,6 +1,6 @@
{
"name": "filament",
"version": "1.29.0",
"version": "1.28.2",
"description": "Real-time physically based rendering engine",
"main": "filament.js",
"module": "filament.js",