Compare commits
9 Commits
v1.28.3
...
bjd/fix-va
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d67e1a9ee8 | ||
|
|
dc44e20be0 | ||
|
|
e64b498d6e | ||
|
|
31ab4a13c9 | ||
|
|
e9728dcc8d | ||
|
|
40a3644086 | ||
|
|
41ef71abdf | ||
|
|
3b40e52c98 | ||
|
|
de8c7969f3 |
@@ -5,8 +5,13 @@ A new header is inserted each time a *tag* is created.
|
||||
|
||||
## main branch
|
||||
|
||||
- backend: add support for GGP platform
|
||||
- gltfio: calculate primitive's AABB correctly.
|
||||
- gltfio: recompute bounding boxes with morph targets
|
||||
- engine: add missing getters on `MaterialInstance`
|
||||
|
||||
## v1.28.3
|
||||
|
||||
- backend: add support for GGP platform
|
||||
- engine: primitives with `CullingMode::FRONT_AND_BACK` are now skipped.
|
||||
|
||||
## v1.28.2
|
||||
|
||||
@@ -452,3 +452,84 @@ Java_com_google_android_filament_MaterialInstance_nDuplicate(JNIEnv* env, jclass
|
||||
}
|
||||
return (jlong)mi;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jfloat JNICALL
|
||||
Java_com_google_android_filament_MaterialInstance_nGetMaskThreshold(JNIEnv* env, jclass clazz,
|
||||
jlong nativeMaterialInstance) {
|
||||
// TODO: implement nGetMaskThreshold()
|
||||
MaterialInstance* instance = (MaterialInstance*)nativeMaterialInstance;
|
||||
return instance->getMaskThreshold();
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jfloat JNICALL
|
||||
Java_com_google_android_filament_MaterialInstance_nGetSpecularAntiAliasingVariance(JNIEnv* env,
|
||||
jclass clazz, jlong nativeMaterialInstance) {
|
||||
// TODO: implement nGetSpecularAntiAliasingVariance()
|
||||
MaterialInstance* instance = (MaterialInstance*)nativeMaterialInstance;
|
||||
return instance->getSpecularAntiAliasingVariance();
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jfloat JNICALL
|
||||
Java_com_google_android_filament_MaterialInstance_nGetSpecularAntiAliasingThreshold(JNIEnv* env,
|
||||
jclass clazz, jlong nativeMaterialInstance) {
|
||||
// TODO: implement nGetSpecularAntiAliasingThreshold()
|
||||
MaterialInstance* instance = (MaterialInstance*)nativeMaterialInstance;
|
||||
return instance->getSpecularAntiAliasingThreshold();
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_com_google_android_filament_MaterialInstance_nIsDoubleSided(JNIEnv* env, jclass clazz,
|
||||
jlong nativeMaterialInstance) {
|
||||
// TODO: implement nIsDoubleSided()
|
||||
MaterialInstance* instance = (MaterialInstance*)nativeMaterialInstance;
|
||||
return instance->isDoubleSided();
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_com_google_android_filament_MaterialInstance_nGetCullingMode(JNIEnv* env, jclass clazz,
|
||||
jlong nativeMaterialInstance) {
|
||||
// TODO: implement nGetCullingMode()
|
||||
MaterialInstance* instance = (MaterialInstance*)nativeMaterialInstance;
|
||||
return (jint)instance->getCullingMode();
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_com_google_android_filament_MaterialInstance_nIsColorWriteEnabled(JNIEnv* env, jclass clazz,
|
||||
jlong nativeMaterialInstance) {
|
||||
// TODO: implement nIsColorWriteEnabled()
|
||||
MaterialInstance* instance = (MaterialInstance*)nativeMaterialInstance;
|
||||
return instance->isColorWriteEnabled();
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_com_google_android_filament_MaterialInstance_nIsDepthWriteEnabled(JNIEnv* env, jclass clazz,
|
||||
jlong nativeMaterialInstance) {
|
||||
// TODO: implement nIsDepthWriteEnabled()
|
||||
MaterialInstance* instance = (MaterialInstance*)nativeMaterialInstance;
|
||||
return instance->isDepthWriteEnabled();
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_com_google_android_filament_MaterialInstance_nIsStencilWriteEnabled(JNIEnv* env, jclass clazz,
|
||||
jlong nativeMaterialInstance) {
|
||||
// TODO: implement nIsStencilWriteEnabled()
|
||||
MaterialInstance* instance = (MaterialInstance*)nativeMaterialInstance;
|
||||
return instance->isStencilWriteEnabled();
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_com_google_android_filament_MaterialInstance_nIsDepthCullingEnabled(JNIEnv* env, jclass clazz,
|
||||
jlong nativeMaterialInstance) {
|
||||
// TODO: implement nIsDepthCullingEnabled()
|
||||
MaterialInstance* instance = (MaterialInstance*)nativeMaterialInstance;
|
||||
return instance->isDepthCullingEnabled();
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ import com.google.android.filament.proguard.UsedByNative;
|
||||
|
||||
@UsedByNative("AssetLoader.cpp")
|
||||
public class MaterialInstance {
|
||||
private static final Material.CullingMode[] sCullingModeValues = Material.CullingMode.values();
|
||||
private Material mMaterial;
|
||||
private String mName;
|
||||
private long mNativeObject;
|
||||
@@ -473,6 +474,14 @@ public class MaterialInstance {
|
||||
nSetMaskThreshold(getNativeObject(), threshold);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the minimum alpha value a fragment must have to not be discarded when the blend
|
||||
* mode is MASKED
|
||||
*/
|
||||
public float getMaskThreshold() {
|
||||
return nGetMaskThreshold(getNativeObject());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the screen space variance of the filter kernel used when applying specular
|
||||
* anti-aliasing. The default value is set to 0.15. The specified value should be between
|
||||
@@ -486,6 +495,14 @@ public class MaterialInstance {
|
||||
nSetSpecularAntiAliasingVariance(getNativeObject(), variance);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the screen space variance of the filter kernel used when applying specular
|
||||
* anti-aliasing.
|
||||
*/
|
||||
public float getSpecularAntiAliasingVariance() {
|
||||
return nGetSpecularAntiAliasingVariance(getNativeObject());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the clamping threshold used to suppress estimation errors when applying specular
|
||||
* anti-aliasing. The default value is set to 0.2. The specified value should be between 0
|
||||
@@ -499,6 +516,14 @@ public class MaterialInstance {
|
||||
nSetSpecularAntiAliasingThreshold(getNativeObject(), threshold);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the clamping threshold used to suppress estimation errors when applying specular
|
||||
* anti-aliasing.
|
||||
*/
|
||||
public float getSpecularAntiAliasingThreshold() {
|
||||
return nGetSpecularAntiAliasingThreshold(getNativeObject());
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables or disables double-sided lighting if the parent Material has double-sided capability,
|
||||
* otherwise prints a warning. If double-sided lighting is enabled, backface culling is
|
||||
@@ -512,6 +537,14 @@ public class MaterialInstance {
|
||||
nSetDoubleSided(getNativeObject(), doubleSided);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether double-sided lighting is enabled when the parent Material has double-sided
|
||||
* capability.
|
||||
*/
|
||||
public boolean isDoubleSided() {
|
||||
return nIsDoubleSided(getNativeObject());
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides the default triangle culling state that was set on the material.
|
||||
*
|
||||
@@ -519,10 +552,18 @@ public class MaterialInstance {
|
||||
* <a href="https://google.github.io/filament/Materials.html#materialdefinitions/materialblock/rasterization:culling">
|
||||
* Rasterization: culling</a>
|
||||
*/
|
||||
public void setCullingMode(Material.CullingMode mode) {
|
||||
public void setCullingMode(@NonNull Material.CullingMode mode) {
|
||||
nSetCullingMode(getNativeObject(), mode.ordinal());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the face culling mode.
|
||||
*/
|
||||
@NonNull
|
||||
public Material.CullingMode getCullingMode() {
|
||||
return sCullingModeValues[nGetCullingMode(getNativeObject())];
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides the default color-buffer write state that was set on the material.
|
||||
*
|
||||
@@ -534,6 +575,13 @@ public class MaterialInstance {
|
||||
nSetColorWrite(getNativeObject(), enable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether color write is enabled.
|
||||
*/
|
||||
public boolean isColorWriteEnabled() {
|
||||
return nIsColorWriteEnabled(getNativeObject());
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides the default depth-buffer write state that was set on the material.
|
||||
*
|
||||
@@ -545,10 +593,27 @@ public class MaterialInstance {
|
||||
nSetDepthWrite(getNativeObject(), enable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether depth write is enabled.
|
||||
*/
|
||||
public boolean isDepthWriteEnabled() {
|
||||
return nIsDepthWriteEnabled(getNativeObject());
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables or Disable stencil writes
|
||||
*/
|
||||
public void setStencilWrite(boolean enable) {
|
||||
nSetStencilWrite(getNativeObject(), enable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether stencil write is enabled.
|
||||
*/
|
||||
public boolean isStencilWriteEnabled() {
|
||||
return nIsStencilWriteEnabled(getNativeObject());
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides the default depth testing state that was set on the material.
|
||||
*
|
||||
@@ -560,6 +625,13 @@ public class MaterialInstance {
|
||||
nSetDepthCulling(getNativeObject(), enable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether depth culling is enabled.
|
||||
*/
|
||||
public boolean isDepthCullingEnabled() {
|
||||
return nIsDepthCullingEnabled(getNativeObject());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the stencil comparison function (default is {@link TextureSampler.CompareFunction#ALWAYS}).
|
||||
*
|
||||
@@ -856,4 +928,15 @@ public class MaterialInstance {
|
||||
private static native long nGetMaterial(long nativeMaterialInstance);
|
||||
|
||||
private static native long nDuplicate(long otherNativeMaterialInstance, String name);
|
||||
|
||||
|
||||
private static native float nGetMaskThreshold(long nativeMaterialInstance);
|
||||
private static native float nGetSpecularAntiAliasingVariance(long nativeMaterialInstance);
|
||||
private static native float nGetSpecularAntiAliasingThreshold(long nativeMaterialInstance);
|
||||
private static native boolean nIsDoubleSided(long nativeMaterialInstance);
|
||||
private static native int nGetCullingMode(long nativeMaterialInstance);
|
||||
private static native boolean nIsColorWriteEnabled(long nativeMaterialInstance);
|
||||
private static native boolean nIsDepthWriteEnabled(long nativeMaterialInstance);
|
||||
private static native boolean nIsStencilWriteEnabled(long nativeMaterialInstance);
|
||||
private static native boolean nIsDepthCullingEnabled(long nativeMaterialInstance);
|
||||
}
|
||||
|
||||
@@ -73,6 +73,7 @@ set(SRCS
|
||||
src/MaterialParser.cpp
|
||||
src/MorphTargetBuffer.cpp
|
||||
src/PerViewUniforms.cpp
|
||||
src/PerShadowMapUniforms.cpp
|
||||
src/PostProcessManager.cpp
|
||||
src/RenderPass.cpp
|
||||
src/RenderPrimitive.cpp
|
||||
@@ -146,6 +147,7 @@ set(PRIVATE_HDRS
|
||||
src/Intersections.h
|
||||
src/MaterialParser.h
|
||||
src/PerViewUniforms.h
|
||||
src/PerShadowMapUniforms.h
|
||||
src/PIDController.h
|
||||
src/PostProcessManager.h
|
||||
src/RendererUtils.h
|
||||
|
||||
@@ -277,6 +277,12 @@ public:
|
||||
*/
|
||||
void setMaskThreshold(float threshold) noexcept;
|
||||
|
||||
/**
|
||||
* Gets the minimum alpha value a fragment must have to not be discarded when the blend
|
||||
* mode is MASKED
|
||||
*/
|
||||
float getMaskThreshold() const noexcept;
|
||||
|
||||
/**
|
||||
* Sets the screen space variance of the filter kernel used when applying specular
|
||||
* anti-aliasing. The default value is set to 0.15. The specified value should be between
|
||||
@@ -284,6 +290,12 @@ public:
|
||||
*/
|
||||
void setSpecularAntiAliasingVariance(float variance) noexcept;
|
||||
|
||||
/**
|
||||
* Gets the screen space variance of the filter kernel used when applying specular
|
||||
* anti-aliasing.
|
||||
*/
|
||||
float getSpecularAntiAliasingVariance() const noexcept;
|
||||
|
||||
/**
|
||||
* Sets the clamping threshold used to suppress estimation errors when applying specular
|
||||
* anti-aliasing. The default value is set to 0.2. The specified value should be between 0
|
||||
@@ -291,6 +303,12 @@ public:
|
||||
*/
|
||||
void setSpecularAntiAliasingThreshold(float threshold) noexcept;
|
||||
|
||||
/**
|
||||
* Gets the clamping threshold used to suppress estimation errors when applying specular
|
||||
* anti-aliasing.
|
||||
*/
|
||||
float getSpecularAntiAliasingThreshold() const noexcept;
|
||||
|
||||
/**
|
||||
* Enables or disables double-sided lighting if the parent Material has double-sided capability,
|
||||
* otherwise prints a warning. If double-sided lighting is enabled, backface culling is
|
||||
@@ -298,36 +316,72 @@ public:
|
||||
*/
|
||||
void setDoubleSided(bool doubleSided) noexcept;
|
||||
|
||||
/**
|
||||
* Returns whether double-sided lighting is enabled when the parent Material has double-sided
|
||||
* capability.
|
||||
*/
|
||||
bool isDoubleSided() const noexcept;
|
||||
|
||||
/**
|
||||
* Specifies how transparent objects should be rendered (default is DEFAULT).
|
||||
*/
|
||||
void setTransparencyMode(TransparencyMode mode) noexcept;
|
||||
|
||||
/**
|
||||
* Returns the transparency mode.
|
||||
*/
|
||||
TransparencyMode getTransparencyMode() const noexcept;
|
||||
|
||||
/**
|
||||
* Overrides the default triangle culling state that was set on the material.
|
||||
*/
|
||||
void setCullingMode(CullingMode culling) noexcept;
|
||||
|
||||
/**
|
||||
* Returns the face culling mode.
|
||||
*/
|
||||
CullingMode getCullingMode() const noexcept;
|
||||
|
||||
/**
|
||||
* Overrides the default color-buffer write state that was set on the material.
|
||||
*/
|
||||
void setColorWrite(bool enable) noexcept;
|
||||
|
||||
/**
|
||||
* Returns whether color write is enabled.
|
||||
*/
|
||||
bool isColorWriteEnabled() const noexcept;
|
||||
|
||||
/**
|
||||
* Overrides the default depth-buffer write state that was set on the material.
|
||||
*/
|
||||
void setDepthWrite(bool enable) noexcept;
|
||||
|
||||
/**
|
||||
* Returns whether depth write is enabled.
|
||||
*/
|
||||
bool isDepthWriteEnabled() const noexcept;
|
||||
|
||||
/**
|
||||
* Overrides the default depth testing state that was set on the material.
|
||||
*/
|
||||
void setDepthCulling(bool enable) noexcept;
|
||||
|
||||
/**
|
||||
* Returns whether depth culling is enabled.
|
||||
*/
|
||||
bool isDepthCullingEnabled() const noexcept;
|
||||
|
||||
/**
|
||||
* Overrides the default stencil-buffer write state that was set on the material.
|
||||
*/
|
||||
void setStencilWrite(bool enable) noexcept;
|
||||
|
||||
/**
|
||||
* Returns whether stencil write is enabled.
|
||||
*/
|
||||
bool isStencilWriteEnabled() const noexcept;
|
||||
|
||||
/**
|
||||
* Sets the stencil comparison function (default is StencilCompareFunc::A).
|
||||
*
|
||||
|
||||
@@ -292,4 +292,44 @@ MaterialInstance* MaterialInstance::duplicate(MaterialInstance const* other, con
|
||||
}
|
||||
|
||||
|
||||
float MaterialInstance::getMaskThreshold() const noexcept {
|
||||
return downcast(this)->getMaskThreshold();
|
||||
}
|
||||
|
||||
float MaterialInstance::getSpecularAntiAliasingVariance() const noexcept {
|
||||
return downcast(this)->getSpecularAntiAliasingVariance();
|
||||
}
|
||||
|
||||
float MaterialInstance::getSpecularAntiAliasingThreshold() const noexcept {
|
||||
return downcast(this)->getSpecularAntiAliasingThreshold();
|
||||
}
|
||||
|
||||
bool MaterialInstance::isDoubleSided() const noexcept {
|
||||
return downcast(this)->isDoubleSided();
|
||||
}
|
||||
|
||||
TransparencyMode MaterialInstance::getTransparencyMode() const noexcept {
|
||||
return downcast(this)->getTransparencyMode();
|
||||
}
|
||||
|
||||
CullingMode MaterialInstance::getCullingMode() const noexcept {
|
||||
return downcast(this)->getCullingMode();
|
||||
}
|
||||
|
||||
bool MaterialInstance::isColorWriteEnabled() const noexcept {
|
||||
return downcast(this)->isColorWriteEnabled();
|
||||
}
|
||||
|
||||
bool MaterialInstance::isDepthWriteEnabled() const noexcept {
|
||||
return downcast(this)->isDepthWriteEnabled();
|
||||
}
|
||||
|
||||
bool MaterialInstance::isStencilWriteEnabled() const noexcept {
|
||||
return downcast(this)->isStencilWriteEnabled();
|
||||
}
|
||||
|
||||
bool MaterialInstance::isDepthCullingEnabled() const noexcept {
|
||||
return downcast(this)->isDepthCullingEnabled();
|
||||
}
|
||||
|
||||
} // namespace filament
|
||||
|
||||
169
filament/src/PerShadowMapUniforms.cpp
Normal file
169
filament/src/PerShadowMapUniforms.cpp
Normal file
@@ -0,0 +1,169 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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 "PerShadowMapUniforms.h"
|
||||
|
||||
#include "ShadowMapManager.h"
|
||||
|
||||
#include "details/Camera.h"
|
||||
#include "details/Engine.h"
|
||||
|
||||
#include <private/filament/EngineEnums.h>
|
||||
|
||||
namespace filament {
|
||||
|
||||
using namespace backend;
|
||||
using namespace math;
|
||||
|
||||
PerShadowMapUniforms::PerShadowMapUniforms(FEngine& engine) noexcept {
|
||||
DriverApi& driver = engine.getDriverApi();
|
||||
mUniformBufferHandle = driver.createBufferObject(sizeof(PerViewUib),
|
||||
BufferObjectBinding::UNIFORM, BufferUsage::DYNAMIC);
|
||||
}
|
||||
|
||||
void PerShadowMapUniforms::terminate(DriverApi& driver) {
|
||||
driver.destroyBufferObject(mUniformBufferHandle);
|
||||
}
|
||||
|
||||
PerViewUib& PerShadowMapUniforms::edit(Transaction const& transaction) noexcept {
|
||||
assert_invariant(transaction.uniforms);
|
||||
return *transaction.uniforms;
|
||||
}
|
||||
|
||||
void PerShadowMapUniforms::prepareCamera(Transaction const& transaction,
|
||||
FEngine& engine, const CameraInfo& camera) noexcept {
|
||||
mat4f const& viewFromWorld = camera.view;
|
||||
mat4f const& worldFromView = camera.model;
|
||||
mat4f const& clipFromView = camera.projection;
|
||||
|
||||
const mat4f viewFromClip{ inverse((mat4)camera.projection) };
|
||||
const mat4f clipFromWorld{ highPrecisionMultiply(clipFromView, viewFromWorld) };
|
||||
const mat4f worldFromClip{ highPrecisionMultiply(worldFromView, viewFromClip) };
|
||||
|
||||
auto& s = edit(transaction);
|
||||
s.viewFromWorldMatrix = viewFromWorld; // view
|
||||
s.worldFromViewMatrix = worldFromView; // model
|
||||
s.clipFromViewMatrix = clipFromView; // projection
|
||||
s.viewFromClipMatrix = viewFromClip; // 1/projection
|
||||
s.clipFromWorldMatrix = clipFromWorld; // projection * view
|
||||
s.worldFromClipMatrix = worldFromClip; // 1/(projection * view)
|
||||
s.clipTransform = camera.clipTransfrom;
|
||||
s.cameraPosition = float3{ camera.getPosition() };
|
||||
s.worldOffset = camera.getWorldOffset();
|
||||
s.cameraFar = camera.zf;
|
||||
s.oneOverFarMinusNear = 1.0f / (camera.zf - camera.zn);
|
||||
s.nearOverFarMinusNear = camera.zn / (camera.zf - camera.zn);
|
||||
|
||||
// with a clip-space of [-w, w] ==> z' = -z
|
||||
// with a clip-space of [0, w] ==> z' = (w - z)/2
|
||||
s.clipControl = engine.getDriverApi().getClipSpaceParams();
|
||||
}
|
||||
|
||||
void PerShadowMapUniforms::prepareLodBias(Transaction const& transaction,
|
||||
float bias) noexcept {
|
||||
auto& s = edit(transaction);
|
||||
s.lodBias = bias;
|
||||
}
|
||||
|
||||
void PerShadowMapUniforms::prepareViewport(Transaction const& transaction,
|
||||
const filament::Viewport& viewport,
|
||||
uint32_t xoffset, uint32_t yoffset) noexcept {
|
||||
const float w = float(viewport.width);
|
||||
const float h = float(viewport.height);
|
||||
auto& s = edit(transaction);
|
||||
s.resolution = float4{ w, h, 1.0f / w, 1.0f / h };
|
||||
s.origin = float2{ viewport.left, viewport.bottom };
|
||||
s.offset = float2{ xoffset, yoffset };
|
||||
}
|
||||
|
||||
void PerShadowMapUniforms::prepareTime(Transaction const& transaction,
|
||||
FEngine& engine, math::float4 const& userTime) noexcept {
|
||||
auto& s = edit(transaction);
|
||||
const uint64_t oneSecondRemainder = engine.getEngineTime().count() % 1000000000;
|
||||
const float fraction = float(double(oneSecondRemainder) / 1000000000.0);
|
||||
s.time = fraction;
|
||||
s.userTime = userTime;
|
||||
}
|
||||
|
||||
void PerShadowMapUniforms::prepareDirectionalLight(Transaction const& transaction,
|
||||
FEngine& engine,
|
||||
float exposure,
|
||||
float3 const& sceneSpaceDirection,
|
||||
PerShadowMapUniforms::LightManagerInstance directionalLight) noexcept {
|
||||
FLightManager& lcm = engine.getLightManager();
|
||||
auto& s = edit(transaction);
|
||||
|
||||
const float3 l = -sceneSpaceDirection; // guaranteed normalized
|
||||
|
||||
if (directionalLight.isValid()) {
|
||||
const float4 colorIntensity = {
|
||||
lcm.getColor(directionalLight), lcm.getIntensity(directionalLight) * exposure };
|
||||
|
||||
s.lightDirection = l;
|
||||
s.lightColorIntensity = colorIntensity;
|
||||
s.lightChannels = lcm.getLightChannels(directionalLight);
|
||||
|
||||
const bool isSun = lcm.isSunLight(directionalLight);
|
||||
// The last parameter must be < 0.0f for regular directional lights
|
||||
float4 sun{ 0.0f, 0.0f, 0.0f, -1.0f };
|
||||
if (UTILS_UNLIKELY(isSun && colorIntensity.w > 0.0f)) {
|
||||
// currently we have only a single directional light, so it's probably likely that it's
|
||||
// also the Sun. However, conceptually, most directional lights won't be sun lights.
|
||||
float radius = lcm.getSunAngularRadius(directionalLight);
|
||||
float haloSize = lcm.getSunHaloSize(directionalLight);
|
||||
float haloFalloff = lcm.getSunHaloFalloff(directionalLight);
|
||||
sun.x = std::cos(radius);
|
||||
sun.y = std::sin(radius);
|
||||
sun.z = 1.0f / (std::cos(radius * haloSize) - sun.x);
|
||||
sun.w = haloFalloff;
|
||||
}
|
||||
s.sun = sun;
|
||||
} else {
|
||||
// Disable the sun if there's no directional light
|
||||
s.sun = float4{ 0.0f, 0.0f, 0.0f, -1.0f };
|
||||
}
|
||||
}
|
||||
|
||||
void PerShadowMapUniforms::prepareShadowMapping(Transaction const& transaction,
|
||||
bool highPrecision) noexcept {
|
||||
auto& s = edit(transaction);
|
||||
constexpr float low = 5.54f; // ~ std::log(std::numeric_limits<math::half>::max()) * 0.5f;
|
||||
constexpr float high = 42.0f; // ~ std::log(std::numeric_limits<float>::max()) * 0.5f;
|
||||
s.vsmExponent = highPrecision ? high : low;
|
||||
}
|
||||
|
||||
|
||||
PerShadowMapUniforms::Transaction PerShadowMapUniforms::open(backend::DriverApi& driver) noexcept {
|
||||
Transaction transaction;
|
||||
// TODO: use out-of-line buffer if too large
|
||||
transaction.uniforms = (PerViewUib *)driver.allocate(sizeof(PerViewUib));
|
||||
assert_invariant(transaction.uniforms);
|
||||
return transaction;
|
||||
}
|
||||
|
||||
void PerShadowMapUniforms::commit(Transaction& transaction,
|
||||
backend::DriverApi& driver) noexcept {
|
||||
driver.updateBufferObject(mUniformBufferHandle, {
|
||||
transaction.uniforms, sizeof(PerViewUib) }, 0);
|
||||
transaction.uniforms = nullptr;
|
||||
}
|
||||
|
||||
void PerShadowMapUniforms::bind(backend::DriverApi& driver) noexcept {
|
||||
driver.bindUniformBuffer(+UniformBindingPoints::PER_VIEW, mUniformBufferHandle);
|
||||
}
|
||||
|
||||
} // namespace filament
|
||||
|
||||
95
filament/src/PerShadowMapUniforms.h
Normal file
95
filament/src/PerShadowMapUniforms.h
Normal file
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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_PERSHADOWMAPUNIFORMS_H
|
||||
#define TNT_FILAMENT_PERSHADOWMAPUNIFORMS_H
|
||||
|
||||
#include <filament/Viewport.h>
|
||||
|
||||
#include <private/filament/UibStructs.h>
|
||||
#include <private/backend/SamplerGroup.h>
|
||||
|
||||
#include "TypedUniformBuffer.h"
|
||||
|
||||
#include <backend/Handle.h>
|
||||
|
||||
#include <utils/EntityInstance.h>
|
||||
|
||||
#include <random>
|
||||
|
||||
namespace filament {
|
||||
|
||||
struct CameraInfo;
|
||||
|
||||
class FEngine;
|
||||
class LightManager;
|
||||
|
||||
/*
|
||||
* PerShadowMapUniforms manages the UBO needed to generate our shadow maps. Internally it just
|
||||
* holds onto a `PerViewUniform` UBO handle, but doesn't keep any shadow copy of it, instead it
|
||||
* writes the data directly into the commandstream, for this reason partial update of the data
|
||||
* is not possible.
|
||||
*/
|
||||
class PerShadowMapUniforms {
|
||||
|
||||
using LightManagerInstance = utils::EntityInstance<LightManager>;
|
||||
|
||||
public:
|
||||
class Transaction {
|
||||
friend PerShadowMapUniforms;
|
||||
PerViewUib* uniforms = nullptr;
|
||||
Transaction() = default; // disallow creation by the caller
|
||||
};
|
||||
|
||||
explicit PerShadowMapUniforms(FEngine& engine) noexcept;
|
||||
|
||||
void terminate(backend::DriverApi& driver);
|
||||
|
||||
static void prepareCamera(Transaction const& transaction,
|
||||
FEngine& engine, const CameraInfo& camera) noexcept;
|
||||
|
||||
static void prepareLodBias(Transaction const& transaction,
|
||||
float bias) noexcept;
|
||||
|
||||
static void prepareViewport(Transaction const& transaction,
|
||||
const filament::Viewport& viewport, uint32_t xoffset, uint32_t yoffset) noexcept;
|
||||
|
||||
static void prepareTime(Transaction const& transaction,
|
||||
FEngine& engine, math::float4 const& userTime) noexcept;
|
||||
|
||||
static void prepareShadowMapping(Transaction const& transaction,
|
||||
bool highPrecision) noexcept;
|
||||
|
||||
static void prepareDirectionalLight(Transaction const& transaction,
|
||||
FEngine& engine, float exposure,
|
||||
math::float3 const& sceneSpaceDirection, LightManagerInstance instance) noexcept;
|
||||
|
||||
static Transaction open(backend::DriverApi& driver) noexcept;
|
||||
|
||||
// update local data into GPU UBO
|
||||
void commit(Transaction& transaction, backend::DriverApi& driver) noexcept;
|
||||
|
||||
// bind this UBO
|
||||
void bind(backend::DriverApi& driver) noexcept;
|
||||
|
||||
private:
|
||||
static PerViewUib& edit(Transaction const& transaction) noexcept;
|
||||
backend::Handle<backend::HwBufferObject> mUniformBufferHandle;
|
||||
};
|
||||
|
||||
} // namespace filament
|
||||
|
||||
#endif //TNT_FILAMENT_PERSHADOWMAPUNIFORMS_H
|
||||
@@ -48,6 +48,11 @@ class FIndirectLight;
|
||||
class Froxelizer;
|
||||
class LightManager;
|
||||
|
||||
/*
|
||||
* PerViewUniforms manages the UBO and samplers needed to render the color passes. Internally it
|
||||
* holds onto handles for the PER_VIEW UBO and SamplerGroup. This class maintains a shadow copy
|
||||
* of the UBO/sampler data, so it is possible to partially update it between commits.
|
||||
*/
|
||||
class PerViewUniforms {
|
||||
|
||||
using LightManagerInstance = utils::EntityInstance<LightManager>;
|
||||
|
||||
@@ -358,8 +358,8 @@ void RenderPass::setupColorCommand(Command& cmdDraw, Variant variant,
|
||||
|
||||
cmdDraw.primitive.rasterState.inverseFrontFaces = inverseFrontFaces;
|
||||
cmdDraw.primitive.rasterState.culling = mi->getCullingMode();
|
||||
cmdDraw.primitive.rasterState.colorWrite = mi->getColorWrite();
|
||||
cmdDraw.primitive.rasterState.depthWrite = mi->getDepthWrite();
|
||||
cmdDraw.primitive.rasterState.colorWrite = mi->isColorWriteEnabled();
|
||||
cmdDraw.primitive.rasterState.depthWrite = mi->isDepthWriteEnabled();
|
||||
cmdDraw.primitive.rasterState.depthFunc = mi->getDepthFunc();
|
||||
cmdDraw.primitive.mi = mi;
|
||||
cmdDraw.primitive.materialVariant = variant;
|
||||
@@ -663,7 +663,7 @@ RenderPass::Command* RenderPass::generateCommandsImpl(uint32_t extraFlags,
|
||||
|
||||
// FIXME: should writeDepthForShadowCasters take precedence over mi->getDepthWrite()?
|
||||
cmdDepth.primitive.rasterState.depthWrite = (1 // only keep bit 0
|
||||
& (mi->getDepthWrite() | (mode == TransparencyMode::TWO_PASSES_ONE_SIDE))
|
||||
& (mi->isDepthWriteEnabled() | (mode == TransparencyMode::TWO_PASSES_ONE_SIDE))
|
||||
& !(filterTranslucentObjects & translucent)
|
||||
& !(depthFilterAlphaMaskedObjects & rs.alphaToCoverage))
|
||||
| writeDepthForShadowCasters;
|
||||
|
||||
@@ -41,7 +41,7 @@ using namespace backend;
|
||||
static constexpr bool USE_DEPTH_CLAMP = false;
|
||||
|
||||
ShadowMap::ShadowMap(FEngine& engine) noexcept
|
||||
: mPerViewUniforms(engine),
|
||||
: mPerShadowMapUniforms(engine),
|
||||
mShadowType(ShadowType::DIRECTIONAL),
|
||||
mHasVisibleShadows(false),
|
||||
mFace(0) {
|
||||
@@ -62,7 +62,7 @@ void ShadowMap::terminate(FEngine& engine) {
|
||||
engine.destroyCameraComponent(e);
|
||||
}
|
||||
engine.getEntityManager().destroy(sizeof(entities) / sizeof(Entity), entities);
|
||||
mPerViewUniforms.terminate(engine.getDriverApi());
|
||||
mPerShadowMapUniforms.terminate(engine.getDriverApi());
|
||||
}
|
||||
|
||||
ShadowMap::~ShadowMap() = default;
|
||||
@@ -1265,34 +1265,45 @@ filament::Viewport ShadowMap::getViewport() const noexcept {
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
void ShadowMap::prepareCamera(FEngine& engine, const CameraInfo& cameraInfo) noexcept {
|
||||
mPerViewUniforms.prepareCamera(engine, cameraInfo);
|
||||
mPerViewUniforms.prepareLodBias(0.0f);
|
||||
void ShadowMap::prepareCamera(Transaction const& transaction,
|
||||
FEngine& engine, const CameraInfo& cameraInfo) noexcept {
|
||||
PerShadowMapUniforms::prepareCamera(transaction, engine, cameraInfo);
|
||||
PerShadowMapUniforms::prepareLodBias(transaction, 0.0f);
|
||||
}
|
||||
|
||||
void ShadowMap::prepareViewport(const filament::Viewport& viewport) noexcept {
|
||||
mPerViewUniforms.prepareViewport(viewport, 0, 0);
|
||||
void ShadowMap::prepareViewport(Transaction const& transaction,
|
||||
const filament::Viewport& viewport) noexcept {
|
||||
PerShadowMapUniforms::prepareViewport(transaction, viewport, 0, 0);
|
||||
}
|
||||
|
||||
void ShadowMap::prepareTime(FEngine& engine, math::float4 const& userTime) noexcept {
|
||||
mPerViewUniforms.prepareTime(engine, userTime);
|
||||
void ShadowMap::prepareTime(Transaction const& transaction,
|
||||
FEngine& engine, math::float4 const& userTime) noexcept {
|
||||
PerShadowMapUniforms::prepareTime(transaction, engine, userTime);
|
||||
}
|
||||
|
||||
void ShadowMap::prepareDirectionalLight(FEngine& engine, math::float3 const& sceneSpaceDirection,
|
||||
void ShadowMap::prepareDirectionalLight(Transaction const& transaction,
|
||||
FEngine& engine, math::float3 const& sceneSpaceDirection,
|
||||
LightManager::Instance instance) noexcept {
|
||||
mPerViewUniforms.prepareDirectionalLight(engine, 1.0f, sceneSpaceDirection, instance);
|
||||
PerShadowMapUniforms::prepareDirectionalLight(transaction,
|
||||
engine, 1.0f, sceneSpaceDirection, instance);
|
||||
}
|
||||
|
||||
void ShadowMap::prepareShadowMapping(bool highPrecision) noexcept {
|
||||
mPerViewUniforms.prepareShadowMapping(highPrecision);
|
||||
void ShadowMap::prepareShadowMapping(Transaction const& transaction,
|
||||
bool highPrecision) noexcept {
|
||||
PerShadowMapUniforms::prepareShadowMapping(transaction, highPrecision);
|
||||
}
|
||||
|
||||
void ShadowMap::commitUniforms(backend::DriverApi& driver) const noexcept {
|
||||
mPerViewUniforms.commit(driver);
|
||||
PerShadowMapUniforms::Transaction ShadowMap::open(DriverApi& driver) noexcept {
|
||||
return PerShadowMapUniforms::open(driver);
|
||||
}
|
||||
|
||||
void ShadowMap::commit(Transaction& transaction,
|
||||
backend::DriverApi& driver) const noexcept {
|
||||
mPerShadowMapUniforms.commit(transaction, driver);
|
||||
}
|
||||
|
||||
void ShadowMap::bindPerViewUniformsAndSamplers(backend::DriverApi& driver) const noexcept {
|
||||
mPerViewUniforms.bind(driver);
|
||||
mPerShadowMapUniforms.bind(driver);
|
||||
}
|
||||
|
||||
} // namespace filament
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
#include "components/LightManager.h"
|
||||
|
||||
#include "PerViewUniforms.h"
|
||||
#include "PerShadowMapUniforms.h"
|
||||
|
||||
#include "details/Camera.h"
|
||||
#include "details/Scene.h"
|
||||
@@ -187,13 +187,22 @@ public:
|
||||
ShadowType getShadowType() const noexcept { return mShadowType; }
|
||||
uint8_t getFace() const noexcept { return mFace; }
|
||||
|
||||
void prepareCamera(FEngine& engine, const CameraInfo& cameraInfo) noexcept;
|
||||
void prepareViewport(const filament::Viewport& viewport) noexcept;
|
||||
void prepareTime(FEngine& engine, math::float4 const& userTime) noexcept;
|
||||
void prepareDirectionalLight(FEngine& engine, math::float3 const& sceneSpaceDirection,
|
||||
using Transaction = PerShadowMapUniforms::Transaction;
|
||||
|
||||
static void prepareCamera(Transaction const& transaction,
|
||||
FEngine& engine, const CameraInfo& cameraInfo) noexcept;
|
||||
static void prepareViewport(Transaction const& transaction,
|
||||
const filament::Viewport& viewport) noexcept;
|
||||
static void prepareTime(Transaction const& transaction,
|
||||
FEngine& engine, math::float4 const& userTime) noexcept;
|
||||
static void prepareDirectionalLight(Transaction const& transaction,
|
||||
FEngine& engine, math::float3 const& sceneSpaceDirection,
|
||||
LightManager::Instance instance) noexcept;
|
||||
void prepareShadowMapping(bool highPrecision) noexcept;
|
||||
void commitUniforms(backend::DriverApi& driver) const noexcept;
|
||||
static void prepareShadowMapping(Transaction const& transaction,
|
||||
bool highPrecision) noexcept;
|
||||
static PerShadowMapUniforms::Transaction open(backend::DriverApi& driver) noexcept;
|
||||
void commit(Transaction& transaction,
|
||||
backend::DriverApi& driver) const noexcept;
|
||||
void bindPerViewUniformsAndSamplers(backend::DriverApi& driver) const noexcept;
|
||||
|
||||
private:
|
||||
@@ -292,12 +301,10 @@ private:
|
||||
{ 2, 6, 7, 3 }, // top
|
||||
};
|
||||
|
||||
// TODO: for shadow maps we don't need the whole `PerViewUniforms` which is large.
|
||||
// replace it with a smaller version that updates only what we need.
|
||||
mutable PerViewUniforms mPerViewUniforms; // 40 + 2048
|
||||
mutable PerShadowMapUniforms mPerShadowMapUniforms; // 4
|
||||
|
||||
FCamera* mCamera = nullptr; // 8
|
||||
FCamera* mDebugCamera = nullptr; // 8
|
||||
FCamera* mCamera = nullptr; // 8
|
||||
FCamera* mDebugCamera = nullptr; // 8
|
||||
|
||||
// The data below technically belongs to ShadowMapManager, but it simplifies allocations
|
||||
// to store it here. This data is always associated with this shadow map anyway.
|
||||
|
||||
@@ -215,9 +215,6 @@ FrameGraphId<FrameGraphTexture> ShadowMapManager::render(FEngine& engine, FrameG
|
||||
// for spot shadow map, we need to do the culling
|
||||
switch (shadowMap.getShadowType()) {
|
||||
case ShadowType::DIRECTIONAL:
|
||||
shadowMap.prepareDirectionalLight(engine,
|
||||
scene->getLightData().elementAt<FScene::DIRECTION>(0),
|
||||
scene->getLightData().elementAt<FScene::LIGHT_INSTANCE>(0));
|
||||
break;
|
||||
case ShadowType::SPOT:
|
||||
prepareSpotShadowMap(shadowMap, engine, view, mainCameraInfo,
|
||||
@@ -245,11 +242,18 @@ FrameGraphId<FrameGraphTexture> ShadowMapManager::render(FEngine& engine, FrameG
|
||||
// cameraInfo only valid after calling update
|
||||
const CameraInfo cameraInfo{ shadowMap.getCamera() };
|
||||
|
||||
shadowMap.prepareCamera(engine, cameraInfo);
|
||||
shadowMap.prepareViewport(shadowMap.getViewport());
|
||||
shadowMap.prepareTime(engine, userTime);
|
||||
shadowMap.prepareShadowMapping(view.getVsmShadowOptions().highPrecision);
|
||||
shadowMap.commitUniforms(driver);
|
||||
auto transaction = ShadowMap::open(driver);
|
||||
ShadowMap::prepareCamera(transaction, engine, cameraInfo);
|
||||
ShadowMap::prepareViewport(transaction, shadowMap.getViewport());
|
||||
ShadowMap::prepareTime(transaction, engine, userTime);
|
||||
ShadowMap::prepareShadowMapping(transaction,
|
||||
view.getVsmShadowOptions().highPrecision);
|
||||
if (shadowMap.getShadowType() == ShadowType::DIRECTIONAL) {
|
||||
ShadowMap::prepareDirectionalLight(transaction, engine,
|
||||
scene->getLightData().elementAt<FScene::DIRECTION>(0),
|
||||
scene->getLightData().elementAt<FScene::LIGHT_INSTANCE>(0));
|
||||
}
|
||||
shadowMap.commit(transaction, driver);
|
||||
|
||||
// updatePrimitivesLod must be run before RenderPass::appendCommands.
|
||||
view.updatePrimitivesLod(engine,
|
||||
|
||||
@@ -219,7 +219,7 @@ private:
|
||||
|
||||
// inline storage for all our ShadowMap objects, we can't easily use a std::array<> directly.
|
||||
// because ShadowMap doesn't have a default ctor, and we avoid out-of-line allocations.
|
||||
// Each ShadowMap is currently 2120 bytes (total of 132KB for 64 shadow maps)
|
||||
// Each ShadowMap is currently 40 bytes (total of 2.5KB for 64 shadow maps)
|
||||
using ShadowMapStorage = std::aligned_storage<sizeof(ShadowMap), alignof(ShadowMap)>::type;
|
||||
std::array<ShadowMapStorage, CONFIG_MAX_SHADOW_LAYERS> mShadowMapCache;
|
||||
};
|
||||
|
||||
@@ -35,17 +35,30 @@ namespace filament {
|
||||
|
||||
using namespace backend;
|
||||
|
||||
FMaterialInstance::FMaterialInstance() noexcept = default;
|
||||
FMaterialInstance::FMaterialInstance() noexcept
|
||||
: mCulling(CullingMode::BACK),
|
||||
mDepthFunc(RasterState::DepthFunc::LE),
|
||||
mColorWrite(false),
|
||||
mDepthWrite(false),
|
||||
mHasScissor(false),
|
||||
mIsDoubleSided(false),
|
||||
mTransparencyMode(TransparencyMode::DEFAULT) {
|
||||
}
|
||||
|
||||
FMaterialInstance::FMaterialInstance(FEngine& engine,
|
||||
FMaterialInstance const* other, const char* name)
|
||||
: mMaterial(other->mMaterial),
|
||||
mPolygonOffset(other->mPolygonOffset),
|
||||
mStencilState(other->mStencilState),
|
||||
mMaskThreshold(other->mMaskThreshold),
|
||||
mSpecularAntiAliasingVariance(other->mSpecularAntiAliasingVariance),
|
||||
mSpecularAntiAliasingThreshold(other->mSpecularAntiAliasingThreshold),
|
||||
mCulling(other->mCulling),
|
||||
mDepthFunc(other->mDepthFunc),
|
||||
mColorWrite(other->mColorWrite),
|
||||
mDepthWrite(other->mDepthWrite),
|
||||
mStencilState(other->mStencilState),
|
||||
mDepthFunc(other->mDepthFunc),
|
||||
mHasScissor(false),
|
||||
mIsDoubleSided(other->mIsDoubleSided),
|
||||
mScissorRect(other->mScissorRect),
|
||||
mName(name ? CString(name) : other->mName) {
|
||||
|
||||
@@ -63,10 +76,23 @@ FMaterialInstance::FMaterialInstance(FEngine& engine,
|
||||
mSbHandle = driver.createSamplerGroup(mSamplers.getSize());
|
||||
}
|
||||
|
||||
mMaterialSortingKey = RenderPass::makeMaterialSortingKey(
|
||||
material->getId(), material->generateMaterialInstanceId());
|
||||
if (material->hasDoubleSidedCapability()) {
|
||||
setDoubleSided(mIsDoubleSided);
|
||||
}
|
||||
|
||||
if (material->getBlendingMode() == BlendingMode::MASKED) {
|
||||
setMaskThreshold(mMaskThreshold);
|
||||
}
|
||||
|
||||
if (material->hasSpecularAntiAliasing()) {
|
||||
setSpecularAntiAliasingThreshold(mSpecularAntiAliasingThreshold);
|
||||
setSpecularAntiAliasingVariance(mSpecularAntiAliasingVariance);
|
||||
}
|
||||
|
||||
setTransparencyMode(material->getTransparencyMode());
|
||||
|
||||
mMaterialSortingKey = RenderPass::makeMaterialSortingKey(
|
||||
material->getId(), material->generateMaterialInstanceId());
|
||||
}
|
||||
|
||||
FMaterialInstance* FMaterialInstance::duplicate(
|
||||
@@ -183,14 +209,29 @@ void FMaterialInstance::setParameterImpl(std::string_view name,
|
||||
|
||||
void FMaterialInstance::setMaskThreshold(float threshold) noexcept {
|
||||
setParameter("_maskThreshold", math::saturate(threshold));
|
||||
mMaskThreshold = math::saturate(threshold);
|
||||
}
|
||||
|
||||
float FMaterialInstance::getMaskThreshold() const noexcept {
|
||||
return mMaskThreshold;
|
||||
}
|
||||
|
||||
void FMaterialInstance::setSpecularAntiAliasingVariance(float variance) noexcept {
|
||||
setParameter("_specularAntiAliasingVariance", math::saturate(variance));
|
||||
mSpecularAntiAliasingVariance = math::saturate(variance);
|
||||
}
|
||||
|
||||
float FMaterialInstance::getSpecularAntiAliasingVariance() const noexcept {
|
||||
return mSpecularAntiAliasingVariance;
|
||||
}
|
||||
|
||||
void FMaterialInstance::setSpecularAntiAliasingThreshold(float threshold) noexcept {
|
||||
setParameter("_specularAntiAliasingThreshold", math::saturate(threshold * threshold));
|
||||
mSpecularAntiAliasingThreshold = std::sqrt(math::saturate(threshold * threshold));
|
||||
}
|
||||
|
||||
float FMaterialInstance::getSpecularAntiAliasingThreshold() const noexcept {
|
||||
return mSpecularAntiAliasingThreshold;
|
||||
}
|
||||
|
||||
void FMaterialInstance::setDoubleSided(bool doubleSided) noexcept {
|
||||
@@ -202,6 +243,11 @@ void FMaterialInstance::setDoubleSided(bool doubleSided) noexcept {
|
||||
if (doubleSided) {
|
||||
setCullingMode(CullingMode::NONE);
|
||||
}
|
||||
mIsDoubleSided = doubleSided;
|
||||
}
|
||||
|
||||
bool FMaterialInstance::isDoubleSided() const noexcept {
|
||||
return mIsDoubleSided;
|
||||
}
|
||||
|
||||
void FMaterialInstance::setTransparencyMode(TransparencyMode mode) noexcept {
|
||||
@@ -212,6 +258,10 @@ void FMaterialInstance::setDepthCulling(bool enable) noexcept {
|
||||
mDepthFunc = enable ? RasterState::DepthFunc::GE : RasterState::DepthFunc::A;
|
||||
}
|
||||
|
||||
bool FMaterialInstance::isDepthCullingEnabled() const noexcept {
|
||||
return mDepthFunc != RasterState::DepthFunc::A;
|
||||
}
|
||||
|
||||
const char* FMaterialInstance::getName() const noexcept {
|
||||
// To decide whether to use the parent material name as a fallback, we check for the nullness of
|
||||
// the instance's CString rather than calling empty(). This allows instances to override the
|
||||
|
||||
@@ -89,9 +89,11 @@ public:
|
||||
|
||||
backend::CullingMode getCullingMode() const noexcept { return mCulling; }
|
||||
|
||||
bool getColorWrite() const noexcept { return mColorWrite; }
|
||||
bool isColorWriteEnabled() const noexcept { return mColorWrite; }
|
||||
|
||||
bool getDepthWrite() const noexcept { return mDepthWrite; }
|
||||
bool isDepthWriteEnabled() const noexcept { return mDepthWrite; }
|
||||
|
||||
bool isStencilWriteEnabled() const noexcept { return mStencilState.stencilWrite; }
|
||||
|
||||
backend::StencilState getStencilState() const noexcept { return mStencilState; }
|
||||
|
||||
@@ -108,12 +110,20 @@ public:
|
||||
|
||||
void setMaskThreshold(float threshold) noexcept;
|
||||
|
||||
float getMaskThreshold() const noexcept;
|
||||
|
||||
void setSpecularAntiAliasingVariance(float variance) noexcept;
|
||||
|
||||
float getSpecularAntiAliasingVariance() const noexcept;
|
||||
|
||||
void setSpecularAntiAliasingThreshold(float threshold) noexcept;
|
||||
|
||||
float getSpecularAntiAliasingThreshold() const noexcept;
|
||||
|
||||
void setDoubleSided(bool doubleSided) noexcept;
|
||||
|
||||
bool isDoubleSided() const noexcept;
|
||||
|
||||
void setTransparencyMode(TransparencyMode mode) noexcept;
|
||||
|
||||
void setCullingMode(CullingMode culling) noexcept { mCulling = culling; }
|
||||
@@ -126,6 +136,8 @@ public:
|
||||
|
||||
void setDepthCulling(bool enable) noexcept;
|
||||
|
||||
bool isDepthCullingEnabled() const noexcept;
|
||||
|
||||
void setStencilCompareFunction(StencilCompareFunc func, StencilFace face) noexcept {
|
||||
if (any(face & StencilFace::FRONT)) {
|
||||
mStencilState.front.stencilFunc = func;
|
||||
@@ -222,19 +234,26 @@ private:
|
||||
|
||||
// keep these grouped, they're accessed together in the render-loop
|
||||
FMaterial const* mMaterial = nullptr;
|
||||
|
||||
backend::Handle<backend::HwBufferObject> mUbHandle;
|
||||
backend::Handle<backend::HwSamplerGroup> mSbHandle;
|
||||
|
||||
UniformBuffer mUniforms;
|
||||
backend::SamplerGroup mSamplers;
|
||||
backend::PolygonOffset mPolygonOffset;
|
||||
backend::CullingMode mCulling;
|
||||
bool mColorWrite;
|
||||
bool mDepthWrite;
|
||||
bool mHasScissor = false;
|
||||
backend::StencilState mStencilState = {};
|
||||
backend::RasterState::DepthFunc mDepthFunc;
|
||||
TransparencyMode mTransparencyMode;
|
||||
|
||||
backend::PolygonOffset mPolygonOffset{};
|
||||
backend::StencilState mStencilState{};
|
||||
|
||||
float mMaskThreshold = 0.0f;
|
||||
float mSpecularAntiAliasingVariance = 0.0f;
|
||||
float mSpecularAntiAliasingThreshold = 0.0f;
|
||||
|
||||
backend::CullingMode mCulling : 2;
|
||||
backend::RasterState::DepthFunc mDepthFunc : 3;
|
||||
bool mColorWrite : 1;
|
||||
bool mDepthWrite : 1;
|
||||
bool mHasScissor : 1;
|
||||
bool mIsDoubleSided : 1;
|
||||
TransparencyMode mTransparencyMode : 2;
|
||||
|
||||
uint64_t mMaterialSortingKey = 0;
|
||||
|
||||
|
||||
@@ -232,14 +232,15 @@ enum class Property : uint8_t {
|
||||
// when adding new Properties, make sure to update MATERIAL_PROPERTIES_COUNT
|
||||
};
|
||||
|
||||
// These flags should match the equivalents in Variant.h.
|
||||
enum class UserVariantFilterBit : uint32_t {
|
||||
DIRECTIONAL_LIGHTING = 0x01,
|
||||
DYNAMIC_LIGHTING = 0x02,
|
||||
SHADOW_RECEIVER = 0x04,
|
||||
SKINNING = 0x08,
|
||||
FOG = 0x10,
|
||||
VSM = 0x20,
|
||||
SSR = 0x40,
|
||||
FOG = 0x20,
|
||||
VSM = 0x40,
|
||||
SSR = VSM | SHADOW_RECEIVER,
|
||||
};
|
||||
|
||||
using UserVariantFilterMask = uint32_t;
|
||||
|
||||
@@ -42,7 +42,7 @@ TEST(ArgBufferFixup, Empty) {
|
||||
TEST(ArgBufferFixup, NoName) {
|
||||
// A valid arg buffer name must be provided to MetalArgumentBuffer.
|
||||
// This assertion is only fired in debug builds.
|
||||
#ifndef NDEBUG
|
||||
#if !defined(NDEBUG) && defined(GTEST_HAS_DEATH_TEST)
|
||||
EXPECT_DEATH({
|
||||
auto argBuffer = MetalArgumentBuffer::Builder().build();
|
||||
MetalArgumentBuffer::destroy(&argBuffer);
|
||||
@@ -56,7 +56,7 @@ TEST(ArgBufferFixup, NoName) {
|
||||
|
||||
TEST(ArgBufferFixup, DuplicateIndices) {
|
||||
// Each index must be unique.
|
||||
#ifndef NDEBUG
|
||||
#if !defined(NDEBUG) && defined(GTEST_HAS_DEATH_TEST)
|
||||
EXPECT_DEATH({
|
||||
auto argBuffer = MetalArgumentBuffer::Builder()
|
||||
.name("myArgumentBuffer")
|
||||
@@ -142,7 +142,7 @@ TEST(ArgBufferFixup, TextureTypes) {
|
||||
|
||||
TEST(ArgBufferFixup, InvalidType) {
|
||||
// All combinations of SamplerType and SamplerFormat are valid except for SAMPLER_3D / SHADOW.
|
||||
#ifndef NDEBUG
|
||||
#if !defined(NDEBUG) && defined(GTEST_HAS_DEATH_TEST)
|
||||
EXPECT_DEATH({
|
||||
auto argBuffer =
|
||||
MetalArgumentBuffer::Builder()
|
||||
|
||||
@@ -991,7 +991,7 @@ bool FAssetLoader::createPrimitive(const cgltf_primitive& inPrim, Primitive* out
|
||||
const float* minp = &accessor->min[0];
|
||||
const float* maxp = &accessor->max[0];
|
||||
|
||||
// We assume that the range of morph target weight is [-1,1].
|
||||
// We assume that the range of morph target weight is [0, 1].
|
||||
targetAabb.min += float3(minp[0], minp[1], minp[2]);
|
||||
targetAabb.max += float3(maxp[0], maxp[1], maxp[2]);
|
||||
|
||||
|
||||
@@ -130,6 +130,45 @@ void FFilamentInstance::recomputeBoundingBoxes() {
|
||||
aabb.min = min(aabb.min, pt);
|
||||
aabb.max = max(aabb.max, pt);
|
||||
}
|
||||
|
||||
if (!prim->targets_count) {
|
||||
break;
|
||||
}
|
||||
|
||||
Aabb baseAabb(aabb);
|
||||
for (cgltf_size targetIndex = 0; targetIndex < prim->targets_count; ++targetIndex) {
|
||||
const cgltf_morph_target& target = prim->targets[targetIndex];
|
||||
for (cgltf_size attribIndex = 0; attribIndex < target.attributes_count; ++attribIndex) {
|
||||
const cgltf_attribute& targetAttribute = target.attributes[attribIndex];
|
||||
if (targetAttribute.type != cgltf_attribute_type_position) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const cgltf_accessor* targetAccessor = targetAttribute.data;
|
||||
const cgltf_size targetCount = targetAccessor->count;
|
||||
const cgltf_size targetDim = cgltf_num_components(targetAccessor->type);
|
||||
|
||||
assert_invariant(targetCount == accessor->count);
|
||||
assert_invariant(targetDim == dim);
|
||||
|
||||
cgltf_accessor_unpack_floats(targetAccessor, unpacked.data(), unpacked.size());
|
||||
|
||||
Aabb targetAabb;
|
||||
for (cgltf_size i = 0, j = 0, n = accessor->count; i < n; ++i, j += dim) {
|
||||
float3 delta(unpacked[j + 0], unpacked[j + 1], unpacked[j + 2]);
|
||||
targetAabb.min = min(targetAabb.min, delta);
|
||||
targetAabb.max = max(targetAabb.max, delta);
|
||||
}
|
||||
|
||||
targetAabb.min += baseAabb.min;
|
||||
targetAabb.max += baseAabb.max;
|
||||
|
||||
aabb.min = min(aabb.min, targetAabb.min);
|
||||
aabb.max = max(aabb.max, targetAabb.max);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -217,7 +217,7 @@ inline bool getElementType(cgltf_type type, cgltf_component_type ctype,
|
||||
*actualType = filament::VertexBuffer::AttributeType::UBYTE3;
|
||||
return true;
|
||||
case cgltf_component_type_r_16:
|
||||
*permitType = filament::VertexBuffer::AttributeType::FLOAT3;
|
||||
*permitType = filament::VertexBuffer::AttributeType::SHORT3;
|
||||
*actualType = filament::VertexBuffer::AttributeType::SHORT3;
|
||||
return true;
|
||||
case cgltf_component_type_r_16u:
|
||||
|
||||
@@ -1250,12 +1250,24 @@ class_<MaterialInstance>("MaterialInstance")
|
||||
self->setParameter(name.c_str(), type, value); }), allow_raw_pointers())
|
||||
.function("setPolygonOffset", &MaterialInstance::setPolygonOffset)
|
||||
.function("setMaskThreshold", &MaterialInstance::setMaskThreshold)
|
||||
.function("getMaskThreshold", &MaterialInstance::getMaskThreshold)
|
||||
.function("setSpecularAntiAliasingVariance", &MaterialInstance::setSpecularAntiAliasingVariance)
|
||||
.function("getSpecularAntiAliasingVariance", &MaterialInstance::getSpecularAntiAliasingVariance)
|
||||
.function("setSpecularAntiAliasingThreshold", &MaterialInstance::setSpecularAntiAliasingThreshold)
|
||||
.function("getSpecularAntiAliasingThreshold", &MaterialInstance::getSpecularAntiAliasingThreshold)
|
||||
.function("setDoubleSided", &MaterialInstance::setDoubleSided)
|
||||
.function("isDoubleSided", &MaterialInstance::isDoubleSided)
|
||||
.function("setTransparencyMode", &MaterialInstance::setTransparencyMode)
|
||||
.function("getTransparencyMode", &MaterialInstance::getTransparencyMode)
|
||||
.function("setCullingMode", &MaterialInstance::setCullingMode)
|
||||
.function("getCullingMode", &MaterialInstance::getCullingMode)
|
||||
.function("setColorWrite", &MaterialInstance::setColorWrite)
|
||||
.function("isColorWriteEnabled", &MaterialInstance::isColorWriteEnabled)
|
||||
.function("setDepthWrite", &MaterialInstance::setDepthWrite)
|
||||
.function("isDepthWriteEnabled", &MaterialInstance::isDepthWriteEnabled)
|
||||
.function("setStencilWrite", &MaterialInstance::setStencilWrite)
|
||||
.function("setDepthCulling", &MaterialInstance::setDepthCulling)
|
||||
.function("isDepthCullingEnabled", &MaterialInstance::isDepthCullingEnabled)
|
||||
.function("setStencilCompareFunction", &MaterialInstance::setStencilCompareFunction)
|
||||
.function("setStencilCompareFunction", EMBIND_LAMBDA(void,
|
||||
(MaterialInstance* self, MaterialInstance::StencilCompareFunc func), {
|
||||
|
||||
@@ -398,6 +398,11 @@ enum_<backend::CullingMode>("CullingMode")
|
||||
.value("BACK", backend::CullingMode::BACK)
|
||||
.value("FRONT_AND_BACK", backend::CullingMode::FRONT_AND_BACK);
|
||||
|
||||
enum_<filament::TransparencyMode>("TransparencyMode")
|
||||
.value("DEFAULT", filament::TransparencyMode::DEFAULT)
|
||||
.value("TWO_PASSES_ONE_SIDE", filament::TransparencyMode::TWO_PASSES_ONE_SIDE)
|
||||
.value("TWO_PASSES_TWO_SIDES", filament::TransparencyMode::TWO_PASSES_TWO_SIDES);
|
||||
|
||||
enum_<backend::FeatureLevel>("FeatureLevel")
|
||||
.value("FEATURE_LEVEL_1", backend::FeatureLevel::FEATURE_LEVEL_1)
|
||||
.value("FEATURE_LEVEL_2", backend::FeatureLevel::FEATURE_LEVEL_2);
|
||||
|
||||
Reference in New Issue
Block a user