Merge branch 'main' into ma/descriptor-sets
This commit is contained in:
@@ -1150,7 +1150,7 @@ struct RasterState {
|
||||
bool inverseFrontFaces : 1; // 31
|
||||
|
||||
//! padding, must be 0
|
||||
uint8_t padding : 1; // 32
|
||||
bool depthClamp : 1; // 32
|
||||
};
|
||||
uint32_t u = 0;
|
||||
};
|
||||
|
||||
@@ -354,6 +354,7 @@ DECL_DRIVER_API_SYNCHRONOUS_0(bool, isParallelShaderCompileSupported)
|
||||
DECL_DRIVER_API_SYNCHRONOUS_0(bool, isDepthStencilResolveSupported)
|
||||
DECL_DRIVER_API_SYNCHRONOUS_N(bool, isDepthStencilBlitSupported, backend::TextureFormat, format)
|
||||
DECL_DRIVER_API_SYNCHRONOUS_0(bool, isProtectedTexturesSupported)
|
||||
DECL_DRIVER_API_SYNCHRONOUS_0(bool, isDepthClampSupported)
|
||||
DECL_DRIVER_API_SYNCHRONOUS_0(uint8_t, getMaxDrawBuffers)
|
||||
DECL_DRIVER_API_SYNCHRONOUS_0(size_t, getMaxUniformBufferSize)
|
||||
DECL_DRIVER_API_SYNCHRONOUS_0(math::float2, getClipSpaceParams)
|
||||
|
||||
@@ -166,6 +166,7 @@ struct MetalContext {
|
||||
std::array<BufferState, MAX_SSBO_COUNT> ssboState;
|
||||
CullModeStateTracker cullModeState;
|
||||
WindingStateTracker windingState;
|
||||
DepthClampStateTracker depthClampState;
|
||||
Handle<HwRenderPrimitive> currentRenderPrimitive;
|
||||
|
||||
// State caches.
|
||||
|
||||
@@ -1061,6 +1061,10 @@ bool MetalDriver::isProtectedTexturesSupported() {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MetalDriver::isDepthClampSupported() {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MetalDriver::isWorkaroundNeeded(Workaround workaround) {
|
||||
switch (workaround) {
|
||||
case Workaround::SPLIT_EASU:
|
||||
@@ -1957,6 +1961,13 @@ void MetalDriver::bindPipeline(PipelineState const& ps) {
|
||||
[mContext->currentRenderPassEncoder setFrontFacingWinding:winding];
|
||||
}
|
||||
|
||||
// depth clip mode
|
||||
MTLDepthClipMode depthClipMode = rs.depthClamp ? MTLDepthClipModeClamp : MTLDepthClipModeClip;
|
||||
mContext->depthClampState.updateState(depthClipMode);
|
||||
if (mContext->depthClampState.stateChanged()) {
|
||||
[mContext->currentRenderPassEncoder setDepthClipMode:depthClipMode];
|
||||
}
|
||||
|
||||
// Set the depth-stencil state, if a state change is needed.
|
||||
DepthStencilState depthState;
|
||||
if (depthAttachment) {
|
||||
|
||||
@@ -379,6 +379,7 @@ using SamplerStateCache = StateCache<SamplerState, id<MTLSamplerState>, SamplerS
|
||||
|
||||
using CullModeStateTracker = StateTracker<MTLCullMode>;
|
||||
using WindingStateTracker = StateTracker<MTLWinding>;
|
||||
using DepthClampStateTracker = StateTracker<MTLDepthClipMode>;
|
||||
|
||||
// Argument encoder
|
||||
|
||||
|
||||
@@ -208,6 +208,10 @@ bool NoopDriver::isProtectedTexturesSupported() {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NoopDriver::isDepthClampSupported() {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NoopDriver::isWorkaroundNeeded(Workaround) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -679,6 +679,7 @@ void OpenGLContext::initExtensionsGLES(Extensions* ext, GLint major, GLint minor
|
||||
#ifndef __EMSCRIPTEN__
|
||||
ext->EXT_debug_marker = exts.has("GL_EXT_debug_marker"sv);
|
||||
#endif
|
||||
ext->EXT_depth_clamp = exts.has("GL_EXT_depth_clamp"sv);
|
||||
ext->EXT_discard_framebuffer = exts.has("GL_EXT_discard_framebuffer"sv);
|
||||
#ifndef __EMSCRIPTEN__
|
||||
ext->EXT_disjoint_timer_query = exts.has("GL_EXT_disjoint_timer_query"sv);
|
||||
@@ -749,6 +750,7 @@ void OpenGLContext::initExtensionsGL(Extensions* ext, GLint major, GLint minor)
|
||||
ext->EXT_color_buffer_half_float = true; // Assumes core profile.
|
||||
ext->EXT_clip_cull_distance = true;
|
||||
ext->EXT_debug_marker = exts.has("GL_EXT_debug_marker"sv);
|
||||
ext->EXT_depth_clamp = true;
|
||||
ext->EXT_discard_framebuffer = false;
|
||||
ext->EXT_disjoint_timer_query = true;
|
||||
ext->EXT_multisampled_render_to_texture = false;
|
||||
|
||||
@@ -224,8 +224,9 @@ public:
|
||||
bool EXT_color_buffer_float;
|
||||
bool EXT_color_buffer_half_float;
|
||||
bool EXT_debug_marker;
|
||||
bool EXT_disjoint_timer_query;
|
||||
bool EXT_depth_clamp;
|
||||
bool EXT_discard_framebuffer;
|
||||
bool EXT_disjoint_timer_query;
|
||||
bool EXT_multisampled_render_to_texture2;
|
||||
bool EXT_multisampled_render_to_texture;
|
||||
bool EXT_protected_textures;
|
||||
@@ -243,10 +244,10 @@ public:
|
||||
bool KHR_parallel_shader_compile;
|
||||
bool KHR_texture_compression_astc_hdr;
|
||||
bool KHR_texture_compression_astc_ldr;
|
||||
bool OES_depth_texture;
|
||||
bool OES_depth24;
|
||||
bool OES_packed_depth_stencil;
|
||||
bool OES_EGL_image_external_essl3;
|
||||
bool OES_depth24;
|
||||
bool OES_depth_texture;
|
||||
bool OES_packed_depth_stencil;
|
||||
bool OES_rgb8_rgba8;
|
||||
bool OES_standard_derivatives;
|
||||
bool OES_texture_npot;
|
||||
@@ -631,6 +632,7 @@ constexpr size_t OpenGLContext::getIndexForCap(GLenum cap) noexcept { //NOLINT
|
||||
#ifdef BACKEND_OPENGL_VERSION_GL
|
||||
case GL_PROGRAM_POINT_SIZE: index = 10; break;
|
||||
#endif
|
||||
case GL_DEPTH_CLAMP: index = 11; break;
|
||||
default: break;
|
||||
}
|
||||
assert_invariant(index < state.enables.caps.size());
|
||||
|
||||
@@ -462,6 +462,14 @@ void OpenGLDriver::setRasterState(RasterState rs) noexcept {
|
||||
} else {
|
||||
gl.disable(GL_SAMPLE_ALPHA_TO_COVERAGE);
|
||||
}
|
||||
|
||||
if (gl.ext.EXT_depth_clamp) {
|
||||
if (rs.depthClamp) {
|
||||
gl.enable(GL_DEPTH_CLAMP);
|
||||
} else {
|
||||
gl.disable(GL_DEPTH_CLAMP);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OpenGLDriver::setStencilState(StencilState ss) noexcept {
|
||||
@@ -2246,6 +2254,10 @@ bool OpenGLDriver::isProtectedTexturesSupported() {
|
||||
return getContext().ext.EXT_protected_textures;
|
||||
}
|
||||
|
||||
bool OpenGLDriver::isDepthClampSupported() {
|
||||
return getContext().ext.EXT_depth_clamp;
|
||||
}
|
||||
|
||||
bool OpenGLDriver::isWorkaroundNeeded(Workaround workaround) {
|
||||
switch (workaround) {
|
||||
case Workaround::SPLIT_EASU:
|
||||
|
||||
@@ -201,6 +201,12 @@ using namespace glext;
|
||||
# define GL_CLIP_DISTANCE1 0x3001
|
||||
#endif
|
||||
|
||||
#if defined(GL_EXT_depth_clamp)
|
||||
# define GL_DEPTH_CLAMP GL_DEPTH_CLAMP_EXT
|
||||
#else
|
||||
# define GL_DEPTH_CLAMP 0x864F
|
||||
#endif
|
||||
|
||||
#if defined(GL_KHR_debug)
|
||||
# define GL_DEBUG_OUTPUT GL_DEBUG_OUTPUT_KHR
|
||||
# define GL_DEBUG_OUTPUT_SYNCHRONOUS GL_DEBUG_OUTPUT_SYNCHRONOUS_KHR
|
||||
|
||||
@@ -125,6 +125,10 @@ public:
|
||||
return mPhysicalDeviceFeatures.imageCubeArray == VK_TRUE;
|
||||
}
|
||||
|
||||
inline bool isDepthClampSupported() const noexcept {
|
||||
return mPhysicalDeviceFeatures.depthClamp == VK_TRUE;
|
||||
}
|
||||
|
||||
inline bool isDebugMarkersSupported() const noexcept {
|
||||
return mDebugMarkersSupported;
|
||||
}
|
||||
|
||||
@@ -1038,6 +1038,10 @@ bool VulkanDriver::isProtectedTexturesSupported() {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool VulkanDriver::isDepthClampSupported() {
|
||||
return mContext.isDepthClampSupported();
|
||||
}
|
||||
|
||||
bool VulkanDriver::isWorkaroundNeeded(Workaround workaround) {
|
||||
switch (workaround) {
|
||||
case Workaround::SPLIT_EASU: {
|
||||
@@ -1823,6 +1827,8 @@ void VulkanDriver::bindPipeline(PipelineState const& pipelineState) {
|
||||
.dstAlphaBlendFactor = getBlendFactor(rasterState.blendFunctionDstAlpha),
|
||||
.colorWriteMask = (VkColorComponentFlags) (rasterState.colorWrite ? 0xf : 0x0),
|
||||
.rasterizationSamples = rt->getSamples(),
|
||||
.depthClamp = rasterState.depthClamp,
|
||||
.reserved = 0,
|
||||
.colorTargetCount = rt->getColorTargetCount(mCurrentRenderPass),
|
||||
.colorBlendOp = rasterState.blendEquationRGB,
|
||||
.alphaBlendOp = rasterState.blendEquationAlpha,
|
||||
|
||||
@@ -184,6 +184,7 @@ VulkanPipelineCache::PipelineCacheEntry* VulkanPipelineCache::createPipeline() n
|
||||
vkRaster.polygonMode = VK_POLYGON_MODE_FILL;
|
||||
vkRaster.cullMode = raster.cullMode;
|
||||
vkRaster.frontFace = raster.frontFace;
|
||||
vkRaster.depthClampEnable = raster.depthClamp;
|
||||
vkRaster.depthBiasEnable = raster.depthBiasEnable;
|
||||
vkRaster.depthBiasConstantFactor = raster.depthBiasConstantFactor;
|
||||
vkRaster.depthBiasClamp = 0.0f;
|
||||
|
||||
@@ -90,7 +90,9 @@ public:
|
||||
VkBlendFactor srcAlphaBlendFactor : 5;
|
||||
VkBlendFactor dstAlphaBlendFactor : 5;
|
||||
VkColorComponentFlags colorWriteMask : 4;
|
||||
uint8_t rasterizationSamples; // offset = 4 bytes
|
||||
uint8_t rasterizationSamples : 4;// offset = 4 bytes
|
||||
uint8_t depthClamp : 1;
|
||||
uint8_t reserved : 3;
|
||||
uint8_t colorTargetCount; // offset = 5 bytes
|
||||
BlendEquation colorBlendOp : 4; // offset = 6 bytes
|
||||
BlendEquation alphaBlendOp : 4;
|
||||
|
||||
@@ -325,6 +325,7 @@ VkDevice createLogicalDevice(VkPhysicalDevice physicalDevice,
|
||||
// We could simply enable all supported features, but since that may have performance
|
||||
// consequences let's just enable the features we need.
|
||||
VkPhysicalDeviceFeatures enabledFeatures{
|
||||
.depthClamp = features.depthClamp,
|
||||
.samplerAnisotropy = features.samplerAnisotropy,
|
||||
.textureCompressionETC2 = features.textureCompressionETC2,
|
||||
.textureCompressionBC = features.textureCompressionBC,
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
#include <utils/compiler.h>
|
||||
#include <utils/Entity.h>
|
||||
#include <utils/FixedCapacityVector.h>
|
||||
|
||||
#include <math/mathfwd.h>
|
||||
|
||||
@@ -727,7 +728,7 @@ public:
|
||||
void setDebugCamera(Camera* UTILS_NULLABLE camera) noexcept;
|
||||
|
||||
//! debugging: returns a Camera from the point of view of *the* dominant directional light used for shadowing.
|
||||
Camera const* UTILS_NULLABLE getDirectionalShadowCamera() const noexcept;
|
||||
utils::FixedCapacityVector<Camera const*> getDirectionalShadowCameras() const noexcept;
|
||||
|
||||
|
||||
/** Result of a picking query */
|
||||
|
||||
@@ -449,7 +449,8 @@ RenderPass::Command* RenderPass::instanceify(FEngine& engine,
|
||||
UTILS_ALWAYS_INLINE // This function exists only to make the code more readable. we want it inlined.
|
||||
inline // and we don't need it in the compilation unit
|
||||
void RenderPass::setupColorCommand(Command& cmdDraw, Variant variant,
|
||||
FMaterialInstance const* const UTILS_RESTRICT mi, bool inverseFrontFaces) noexcept {
|
||||
FMaterialInstance const* const UTILS_RESTRICT mi,
|
||||
bool inverseFrontFaces, bool hasDepthClamp) noexcept {
|
||||
|
||||
FMaterial const * const UTILS_RESTRICT ma = mi->getMaterial();
|
||||
variant = Variant::filterVariant(variant, ma->isVariantLit());
|
||||
@@ -490,6 +491,7 @@ void RenderPass::setupColorCommand(Command& cmdDraw, Variant variant,
|
||||
cmdDraw.info.rasterState.colorWrite = mi->isColorWriteEnabled();
|
||||
cmdDraw.info.rasterState.depthWrite = mi->isDepthWriteEnabled();
|
||||
cmdDraw.info.rasterState.depthFunc = mi->getDepthFunc();
|
||||
cmdDraw.info.rasterState.depthClamp = hasDepthClamp;
|
||||
cmdDraw.info.materialVariant = variant;
|
||||
// we keep "RasterState::colorWrite" to the value set by material (could be disabled)
|
||||
}
|
||||
@@ -587,6 +589,9 @@ RenderPass::Command* RenderPass::generateCommandsImpl(RenderPass::CommandTypeFla
|
||||
bool const hasInstancedStereo =
|
||||
renderFlags & IS_INSTANCED_STEREOSCOPIC;
|
||||
|
||||
bool const hasDepthClamp =
|
||||
renderFlags & HAS_DEPTH_CLAMP;
|
||||
|
||||
float const cameraPositionDotCameraForward = dot(cameraPosition, cameraForward);
|
||||
|
||||
auto const* const UTILS_RESTRICT soaWorldAABBCenter = soa.data<FScene::WORLD_AABB_CENTER>();
|
||||
@@ -607,6 +612,7 @@ RenderPass::Command* RenderPass::generateCommandsImpl(RenderPass::CommandTypeFla
|
||||
cmd.info.rasterState.depthWrite = true;
|
||||
cmd.info.rasterState.depthFunc = RasterState::DepthFunc::GE;
|
||||
cmd.info.rasterState.alphaToCoverage = false;
|
||||
cmd.info.rasterState.depthClamp = hasDepthClamp;
|
||||
}
|
||||
|
||||
for (uint32_t i = range.first; i < range.last; ++i) {
|
||||
@@ -722,7 +728,8 @@ RenderPass::Command* RenderPass::generateCommandsImpl(RenderPass::CommandTypeFla
|
||||
// morphing.morphTargetBuffer->getHwHandle() : SamplerGroupHandle{};
|
||||
|
||||
if constexpr (isColorPass) {
|
||||
RenderPass::setupColorCommand(cmd, renderableVariant, mi, inverseFrontFaces);
|
||||
RenderPass::setupColorCommand(cmd, renderableVariant, mi,
|
||||
inverseFrontFaces, hasDepthClamp);
|
||||
const bool blendPass = Pass(cmd.key & PASS_MASK) == Pass::BLENDED;
|
||||
if (blendPass) {
|
||||
// TODO: at least for transparent objects, AABB should be per primitive
|
||||
|
||||
@@ -285,6 +285,7 @@ public:
|
||||
static constexpr RenderFlags HAS_SHADOWING = 0x01;
|
||||
static constexpr RenderFlags HAS_INVERSE_FRONT_FACES = 0x02;
|
||||
static constexpr RenderFlags IS_INSTANCED_STEREOSCOPIC = 0x04;
|
||||
static constexpr RenderFlags HAS_DEPTH_CLAMP = 0x08;
|
||||
|
||||
// Arena used for commands
|
||||
using Arena = utils::Arena<
|
||||
@@ -453,7 +454,7 @@ private:
|
||||
uint8_t instancedStereoEyeCount) noexcept;
|
||||
|
||||
static void setupColorCommand(Command& cmdDraw, Variant variant,
|
||||
FMaterialInstance const* mi, bool inverseFrontFaces) noexcept;
|
||||
FMaterialInstance const* mi, bool inverseFrontFaces, bool hasDepthClamp) noexcept;
|
||||
|
||||
static void updateSummedPrimitiveCounts(
|
||||
FScene::RenderableSoa& renderableData, utils::Range<uint32_t> vr) noexcept;
|
||||
|
||||
@@ -829,13 +829,13 @@ ShadowMap::Corners ShadowMap::computeFrustumCorners(
|
||||
Corners const csViewFrustumCorners = {
|
||||
.vertices = {
|
||||
{ -1, -1, far },
|
||||
{ 1, -1, far },
|
||||
{ -1, 1, far },
|
||||
{ 1, 1, far },
|
||||
{ 1, -1, far },
|
||||
{ -1, 1, far },
|
||||
{ 1, 1, far },
|
||||
{ -1, -1, near },
|
||||
{ 1, -1, near },
|
||||
{ -1, 1, near },
|
||||
{ 1, 1, near },
|
||||
{ 1, -1, near },
|
||||
{ -1, 1, near },
|
||||
{ 1, 1, near },
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -66,15 +66,15 @@ namespace filament {
|
||||
using namespace backend;
|
||||
using namespace math;
|
||||
|
||||
// do this only if depth-clamp is available
|
||||
static constexpr bool USE_DEPTH_CLAMP = false;
|
||||
|
||||
ShadowMapManager::ShadowMapManager(FEngine& engine) {
|
||||
ShadowMapManager::ShadowMapManager(FEngine& engine)
|
||||
: mIsDepthClampSupported(engine.getDriverApi().isDepthClampSupported()) {
|
||||
FDebugRegistry& debugRegistry = engine.getDebugRegistry();
|
||||
debugRegistry.registerProperty("d.shadowmap.visualize_cascades",
|
||||
&engine.debug.shadowmap.visualize_cascades);
|
||||
debugRegistry.registerProperty("d.shadowmap.disable_light_frustum_align",
|
||||
&engine.debug.shadowmap.disable_light_frustum_align);
|
||||
debugRegistry.registerProperty("d.shadowmap.depth_clamp",
|
||||
&engine.debug.shadowmap.depth_clamp);
|
||||
}
|
||||
|
||||
ShadowMapManager::~ShadowMapManager() {
|
||||
@@ -367,7 +367,16 @@ FrameGraphId<FrameGraphTexture> ShadowMapManager::render(FEngine& engine, FrameG
|
||||
|
||||
// generate and sort the commands for rendering the shadow map
|
||||
|
||||
RenderPass::RenderFlags renderPassFlags{};
|
||||
if (view.isFrontFaceWindingInverted()) {
|
||||
renderPassFlags |= RenderPass::HAS_INVERSE_FRONT_FACES;
|
||||
}
|
||||
if (mIsDepthClampSupported && engine.debug.shadowmap.depth_clamp) {
|
||||
renderPassFlags |= RenderPass::HAS_DEPTH_CLAMP;
|
||||
}
|
||||
|
||||
RenderPass const pass = passBuilder
|
||||
.renderFlags(renderPassFlags)
|
||||
.camera(cameraInfo)
|
||||
.visibilityMask(entry.visibilityMask)
|
||||
.geometry(scene->getRenderableData(), entry.range)
|
||||
@@ -638,7 +647,8 @@ ShadowMapManager::ShadowTechnique ShadowMapManager::updateCascadeShadowMaps(FEng
|
||||
updateNearFarPlanes(&cameraInfo.cullingProjection, cameraInfo.zn, cameraInfo.zf);
|
||||
|
||||
auto shaderParameters = shadowMap.updateDirectional(engine,
|
||||
lightData, 0, cameraInfo, shadowMapInfo, sceneInfo, USE_DEPTH_CLAMP);
|
||||
lightData, 0, cameraInfo, shadowMapInfo, sceneInfo,
|
||||
mIsDepthClampSupported && engine.debug.shadowmap.depth_clamp);
|
||||
|
||||
if (shadowMap.hasVisibleShadows()) {
|
||||
const size_t shadowIndex = shadowMap.getShadowIndex();
|
||||
@@ -1072,4 +1082,15 @@ void ShadowMapManager::updateNearFarPlanes(mat4f* projection,
|
||||
p[3].z = (sf * F.w - sn * N.w) * 0.5f;
|
||||
}
|
||||
|
||||
utils::FixedCapacityVector<Camera const*>
|
||||
ShadowMapManager::getDirectionalShadowCameras() const noexcept {
|
||||
if (!mInitialized) return {};
|
||||
auto const csm = getCascadedShadowMap();
|
||||
auto result = utils::FixedCapacityVector<Camera const*>::with_capacity(csm.size());
|
||||
for (ShadowMap const& sm : csm) {
|
||||
result.push_back(sm.hasVisibleShadows() ? sm.getDebugCamera() : nullptr);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace filament
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
|
||||
#include <utils/BitmaskEnum.h>
|
||||
#include <utils/compiler.h>
|
||||
#include <utils/FixedCapacityVector.h>
|
||||
#include <utils/debug.h>
|
||||
#include <utils/Range.h>
|
||||
#include <utils/Slice.h>
|
||||
@@ -58,6 +59,7 @@
|
||||
|
||||
namespace filament {
|
||||
|
||||
class Camera;
|
||||
class FCamera;
|
||||
class FView;
|
||||
class FrameGraph;
|
||||
@@ -138,10 +140,7 @@ public:
|
||||
bool hasSpotShadows() const { return !mSpotShadowMapCount; }
|
||||
|
||||
// for debugging only
|
||||
FCamera const* getDirectionalShadowCamera() const noexcept {
|
||||
if (!mInitialized) return nullptr;
|
||||
return getShadowMap(0).getDebugCamera();
|
||||
}
|
||||
utils::FixedCapacityVector<Camera const*> getDirectionalShadowCameras() const noexcept;
|
||||
|
||||
private:
|
||||
explicit ShadowMapManager(FEngine& engine);
|
||||
@@ -233,6 +232,7 @@ private:
|
||||
ShadowMapCacheContainer mShadowMapCache;
|
||||
uint32_t mDirectionalShadowMapCount = 0;
|
||||
uint32_t mSpotShadowMapCount = 0;
|
||||
bool const mIsDepthClampSupported;
|
||||
bool mInitialized = false;
|
||||
|
||||
ShadowMap& getShadowMap(size_t index) noexcept {
|
||||
@@ -245,10 +245,14 @@ private:
|
||||
}
|
||||
|
||||
utils::Slice<ShadowMap> getCascadedShadowMap() noexcept {
|
||||
ShadowMap* const p = &getShadowMap(0);
|
||||
ShadowMap const* const p = &getShadowMap(0);
|
||||
return { p, mDirectionalShadowMapCount };
|
||||
}
|
||||
|
||||
utils::Slice<ShadowMap> getCascadedShadowMap() const noexcept {
|
||||
return const_cast<ShadowMapManager*>(this)->getCascadedShadowMap();
|
||||
}
|
||||
|
||||
utils::Slice<ShadowMap> getSpotShadowMaps() noexcept {
|
||||
ShadowMap* const p = &getShadowMap(CONFIG_MAX_SHADOW_CASCADES);
|
||||
return { p, mSpotShadowMapCount };
|
||||
|
||||
@@ -73,8 +73,8 @@ const char* View::getName() const noexcept {
|
||||
return downcast(this)->getName();
|
||||
}
|
||||
|
||||
Camera const* View::getDirectionalShadowCamera() const noexcept {
|
||||
return downcast(this)->getDirectionalShadowCamera();
|
||||
utils::FixedCapacityVector<Camera const*> View::getDirectionalShadowCameras() const noexcept {
|
||||
return downcast(this)->getDirectionalShadowCameras();
|
||||
}
|
||||
|
||||
void View::setShadowingEnabled(bool enabled) noexcept {
|
||||
|
||||
@@ -28,12 +28,6 @@
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
|
||||
#ifndef NDEBUG
|
||||
# define DEBUG_PROPERTIES_WRITABLE true
|
||||
#else
|
||||
# define DEBUG_PROPERTIES_WRITABLE false
|
||||
#endif
|
||||
|
||||
using namespace filament::math;
|
||||
using namespace utils;
|
||||
|
||||
@@ -79,17 +73,15 @@ bool FDebugRegistry::hasProperty(const char* name) const noexcept {
|
||||
|
||||
template<typename T>
|
||||
bool FDebugRegistry::setProperty(const char* name, T v) noexcept {
|
||||
if constexpr (DEBUG_PROPERTIES_WRITABLE) {
|
||||
auto info = getPropertyInfo(name);
|
||||
T* const addr = static_cast<T*>(info.first);
|
||||
if (addr) {
|
||||
auto old = *addr;
|
||||
*addr = v;
|
||||
if (info.second && old != v) {
|
||||
info.second();
|
||||
}
|
||||
return true;
|
||||
auto info = getPropertyInfo(name);
|
||||
T* const addr = static_cast<T*>(info.first);
|
||||
if (addr) {
|
||||
auto old = *addr;
|
||||
*addr = v;
|
||||
if (info.second && old != v) {
|
||||
info.second();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -617,6 +617,7 @@ public:
|
||||
bool focus_shadowcasters = true;
|
||||
bool visualize_cascades = false;
|
||||
bool disable_light_frustum_align = false;
|
||||
bool depth_clamp = true;
|
||||
float dzn = -1.0f;
|
||||
float dzf = 1.0f;
|
||||
float display_shadow_texture_scale = 0.25f;
|
||||
|
||||
@@ -212,9 +212,9 @@ public:
|
||||
|
||||
void setStereoscopicOptions(StereoscopicOptions const& options) noexcept;
|
||||
|
||||
FCamera const* getDirectionalShadowCamera() const noexcept {
|
||||
if (!mShadowMapManager) return nullptr;
|
||||
return mShadowMapManager->getDirectionalShadowCamera();
|
||||
utils::FixedCapacityVector<Camera const*> getDirectionalShadowCameras() const noexcept {
|
||||
if (!mShadowMapManager) return {};
|
||||
return mShadowMapManager->getDirectionalShadowCameras();
|
||||
}
|
||||
|
||||
void setRenderTarget(FRenderTarget* renderTarget) noexcept {
|
||||
|
||||
@@ -28,8 +28,14 @@
|
||||
|
||||
class Cube {
|
||||
public:
|
||||
|
||||
Cube(filament::Engine& engine, filament::Material const* material, filament::math::float3 linearColor, bool culling = true);
|
||||
|
||||
Cube(Cube const&) = delete;
|
||||
Cube& operator=(Cube const&) = delete;
|
||||
|
||||
Cube(Cube&& rhs) noexcept;
|
||||
|
||||
utils::Entity getSolidRenderable() {
|
||||
return mSolidRenderable;
|
||||
}
|
||||
@@ -55,8 +61,8 @@ private:
|
||||
filament::Material const* mMaterial = nullptr;
|
||||
filament::MaterialInstance* mMaterialInstanceSolid = nullptr;
|
||||
filament::MaterialInstance* mMaterialInstanceWireFrame = nullptr;
|
||||
utils::Entity mSolidRenderable;
|
||||
utils::Entity mWireFrameRenderable;
|
||||
utils::Entity mSolidRenderable{};
|
||||
utils::Entity mWireFrameRenderable{};
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -211,11 +211,11 @@ private:
|
||||
filament::Camera* mOrthoCamera;
|
||||
|
||||
std::vector<std::unique_ptr<CView>> mViews;
|
||||
CView* mMainView;
|
||||
CView* mUiView;
|
||||
CView* mMainView; // well, the main view
|
||||
CView* mUiView; // the imgui ui
|
||||
CView* mDepthView;
|
||||
GodView* mGodView;
|
||||
CView* mOrthoView;
|
||||
GodView* mGodView; // the debug view with "god" camera
|
||||
CView* mOrthoView; // directional shadow map view
|
||||
|
||||
size_t mWidth = 0;
|
||||
size_t mHeight = 0;
|
||||
|
||||
@@ -104,11 +104,23 @@ Cube::Cube(Engine& engine, filament::Material const* material, float3 linearColo
|
||||
.build(engine, mWireFrameRenderable);
|
||||
}
|
||||
|
||||
Cube::Cube(Cube&& rhs) noexcept
|
||||
: mEngine(rhs.mEngine) {
|
||||
using std::swap;
|
||||
swap(rhs.mVertexBuffer, mVertexBuffer);
|
||||
swap(rhs.mIndexBuffer, mIndexBuffer);
|
||||
swap(rhs.mMaterial, mMaterial);
|
||||
swap(rhs.mMaterialInstanceSolid, mMaterialInstanceSolid);
|
||||
swap(rhs.mMaterialInstanceWireFrame, mMaterialInstanceWireFrame);
|
||||
swap(rhs.mSolidRenderable, mSolidRenderable);
|
||||
swap(rhs.mWireFrameRenderable, mWireFrameRenderable);
|
||||
}
|
||||
|
||||
void Cube::mapFrustum(filament::Engine& engine, Camera const* camera) {
|
||||
// the Camera far plane is at infinity, but we want it closer for display
|
||||
const mat4 vm(camera->getModelMatrix());
|
||||
mat4 p(vm * inverse(camera->getCullingProjectionMatrix()));
|
||||
return mapFrustum(engine, p);
|
||||
mapFrustum(engine, p);
|
||||
}
|
||||
|
||||
void Cube::mapFrustum(filament::Engine& engine, filament::math::mat4 const& transform) {
|
||||
@@ -122,7 +134,7 @@ void Cube::mapFrustum(filament::Engine& engine, filament::math::mat4 const& tran
|
||||
|
||||
void Cube::mapAabb(filament::Engine& engine, filament::Box const& box) {
|
||||
mat4 p = mat4::translation(box.center) * mat4::scaling(box.halfExtent);
|
||||
return mapFrustum(engine, p);
|
||||
mapFrustum(engine, p);
|
||||
}
|
||||
|
||||
Cube::~Cube() {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
#include <memory>
|
||||
|
||||
/*
|
||||
* Copyright (C) 2015 The Android Open Source Project
|
||||
@@ -56,6 +55,13 @@
|
||||
|
||||
#include <stb_image.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdlib>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "generated/resources/filamentapp.h"
|
||||
|
||||
using namespace filament;
|
||||
@@ -138,10 +144,17 @@ void FilamentApp::run(const Config& config, SetupCallback setupCallback,
|
||||
.package(FILAMENTAPP_TRANSPARENTCOLOR_DATA, FILAMENTAPP_TRANSPARENTCOLOR_SIZE)
|
||||
.build(*mEngine);
|
||||
|
||||
std::unique_ptr<Cube> cameraCube(new Cube(*mEngine, mTransparentMaterial, {1,0,0}));
|
||||
std::unique_ptr<Cube> cameraCube{ new Cube(*mEngine, mTransparentMaterial, { 1, 0, 0 }) };
|
||||
|
||||
// we can't cull the light-frustum because it's not applied a rigid transform
|
||||
// and currently, filament assumes that for culling
|
||||
std::unique_ptr<Cube> lightmapCube(new Cube(*mEngine, mTransparentMaterial, {0,1,0}, false));
|
||||
std::vector<Cube> lightmapCubes;
|
||||
lightmapCubes.reserve(4);
|
||||
lightmapCubes.emplace_back(*mEngine, mTransparentMaterial, float3{ 0, 1, 0 }, false);
|
||||
lightmapCubes.emplace_back(*mEngine, mTransparentMaterial, float3{ 0, 0, 1 }, false);
|
||||
lightmapCubes.emplace_back(*mEngine, mTransparentMaterial, float3{ 1, 1, 0 }, false);
|
||||
lightmapCubes.emplace_back(*mEngine, mTransparentMaterial, float3{ 1, 0, 0 }, false);
|
||||
|
||||
mScene = mEngine->createScene();
|
||||
|
||||
window->mMainView->getView()->setVisibleLayers(0x4, 0x4);
|
||||
@@ -151,16 +164,15 @@ void FilamentApp::run(const Config& config, SetupCallback setupCallback,
|
||||
|
||||
rcm.setLayerMask(rcm.getInstance(cameraCube->getSolidRenderable()), 0x3, 0x2);
|
||||
rcm.setLayerMask(rcm.getInstance(cameraCube->getWireFrameRenderable()), 0x3, 0x2);
|
||||
|
||||
rcm.setLayerMask(rcm.getInstance(lightmapCube->getSolidRenderable()), 0x3, 0x2);
|
||||
rcm.setLayerMask(rcm.getInstance(lightmapCube->getWireFrameRenderable()), 0x3, 0x2);
|
||||
|
||||
// Create the camera mesh
|
||||
mScene->addEntity(cameraCube->getWireFrameRenderable());
|
||||
mScene->addEntity(cameraCube->getSolidRenderable());
|
||||
|
||||
mScene->addEntity(lightmapCube->getWireFrameRenderable());
|
||||
mScene->addEntity(lightmapCube->getSolidRenderable());
|
||||
for (auto&& cube : lightmapCubes) {
|
||||
rcm.setLayerMask(rcm.getInstance(cube.getSolidRenderable()), 0x3, 0x2);
|
||||
rcm.setLayerMask(rcm.getInstance(cube.getWireFrameRenderable()), 0x3, 0x2);
|
||||
mScene->addEntity(cube.getWireFrameRenderable());
|
||||
mScene->addEntity(cube.getSolidRenderable());
|
||||
}
|
||||
|
||||
window->mDepthView->getView()->setVisibleLayers(0x4, 0x4);
|
||||
window->mGodView->getView()->setVisibleLayers(0x6, 0x6);
|
||||
@@ -425,10 +437,26 @@ void FilamentApp::run(const Config& config, SetupCallback setupCallback,
|
||||
window->mDebugCamera->lookAt(eye, center, up);
|
||||
|
||||
// Update the cube distortion matrix used for frustum visualization.
|
||||
const Camera* lightmapCamera = window->mMainView->getView()->getDirectionalShadowCamera();
|
||||
if (lightmapCamera) {
|
||||
lightmapCube->mapFrustum(*mEngine, lightmapCamera);
|
||||
auto& rcm = mEngine->getRenderableManager();
|
||||
auto const csm = window->mMainView->getView()->getDirectionalShadowCameras();
|
||||
// show/hide the cascades
|
||||
for (size_t i = 0 ; i < 4; i++) {
|
||||
rcm.setLayerMask(rcm.getInstance(lightmapCubes[i].getSolidRenderable()), 0x3, 0x0);
|
||||
rcm.setLayerMask(rcm.getInstance(lightmapCubes[i].getWireFrameRenderable()), 0x3, 0x0);
|
||||
}
|
||||
if (!csm.empty()) {
|
||||
for (size_t i = 0, c = csm.size(); i < c; i++) {
|
||||
if (csm[i]) {
|
||||
lightmapCubes[i].mapFrustum(*mEngine, csm[i]);
|
||||
}
|
||||
uint8_t const layer = csm[i] ? 0x2 : 0x0;
|
||||
rcm.setLayerMask(rcm.getInstance(lightmapCubes[i].getSolidRenderable()),
|
||||
0x3, layer);
|
||||
rcm.setLayerMask(rcm.getInstance(lightmapCubes[i].getWireFrameRenderable()),
|
||||
0x3, layer);
|
||||
}
|
||||
}
|
||||
|
||||
cameraCube->mapFrustum(*mEngine, window->mMainCamera);
|
||||
|
||||
// Delay rendering for roughly one monitor refresh interval
|
||||
@@ -452,11 +480,14 @@ void FilamentApp::run(const Config& config, SetupCallback setupCallback,
|
||||
|
||||
if (config.splitView) {
|
||||
if(!window->mOrthoView->getView()->hasCamera()) {
|
||||
Camera const* debugDirectionalShadowCamera =
|
||||
window->mMainView->getView()->getDirectionalShadowCamera();
|
||||
if (debugDirectionalShadowCamera) {
|
||||
window->mOrthoView->setCamera(
|
||||
const_cast<Camera*>(debugDirectionalShadowCamera));
|
||||
auto const csm = window->mMainView->getView()->getDirectionalShadowCameras();
|
||||
if (!csm.empty()) {
|
||||
// here we could choose the cascade
|
||||
Camera const* debugDirectionalShadowCamera = csm[0];
|
||||
if (debugDirectionalShadowCamera) {
|
||||
window->mOrthoView->setCamera(
|
||||
const_cast<Camera*>(debugDirectionalShadowCamera));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -484,7 +515,7 @@ void FilamentApp::run(const Config& config, SetupCallback setupCallback,
|
||||
cleanupCallback(mEngine, window->mMainView->getView(), mScene);
|
||||
|
||||
cameraCube.reset();
|
||||
lightmapCube.reset();
|
||||
lightmapCubes.clear();
|
||||
window.reset();
|
||||
|
||||
mIBL.reset();
|
||||
@@ -736,12 +767,6 @@ FilamentApp::Window::Window(FilamentApp* filamentApp,
|
||||
mGodView->setCamera(mMainCamera);
|
||||
mGodView->setGodCamera(mDebugCamera);
|
||||
mGodView->setCameraManipulator(mDebugCameraMan);
|
||||
|
||||
// Ortho view obviously uses an ortho camera
|
||||
Camera const* debugDirectionalShadowCamera = mMainView->getView()->getDirectionalShadowCamera();
|
||||
if (debugDirectionalShadowCamera) {
|
||||
mOrthoView->setCamera(const_cast<Camera *>(debugDirectionalShadowCamera));
|
||||
}
|
||||
}
|
||||
|
||||
// configure the cameras
|
||||
@@ -907,9 +932,7 @@ void FilamentApp::Window::configureCamerasForWindow() {
|
||||
|
||||
const bool splitview = mViews.size() > 2;
|
||||
|
||||
// To trigger a floating-point exception, users could shrink the window to be smaller than
|
||||
// the sidebar. To prevent this we simply clamp the width of the main viewport.
|
||||
const uint32_t mainWidth = splitview ? width : std::max(1, (int) width - sidebar);
|
||||
const uint32_t mainWidth = std::max(2, (int) width - sidebar);
|
||||
|
||||
double near = mFilamentApp->mCameraNear;
|
||||
double far = mFilamentApp->mCameraFar;
|
||||
@@ -924,7 +947,7 @@ void FilamentApp::Window::configureCamerasForWindow() {
|
||||
} else {
|
||||
mMainCamera->setLensProjection(mFilamentApp->mCameraFocalLength, 1.0, near, far);
|
||||
}
|
||||
mDebugCamera->setProjection(45.0, double(width) / height, 0.0625, 4096, Camera::Fov::VERTICAL);
|
||||
mDebugCamera->setProjection(45.0, double(mainWidth) / height, 0.0625, 4096, Camera::Fov::VERTICAL);
|
||||
|
||||
auto aspectRatio = double(mainWidth) / height;
|
||||
if (mMainView->getView()->getStereoscopicOptions().enabled) {
|
||||
@@ -935,12 +958,12 @@ void FilamentApp::Window::configureCamerasForWindow() {
|
||||
|
||||
// We're in split view when there are more views than just the Main and UI views.
|
||||
if (splitview) {
|
||||
uint32_t vpw = width / 2;
|
||||
uint32_t vph = height / 2;
|
||||
mMainView->setViewport ({ 0, 0, vpw, vph });
|
||||
mDepthView->setViewport({ int32_t(vpw), 0, width - vpw, vph });
|
||||
mGodView->setViewport ({ int32_t(vpw), int32_t(vph), width - vpw, height - vph });
|
||||
mOrthoView->setViewport({ 0, int32_t(vph), vpw, height - vph });
|
||||
uint32_t const vpw = mainWidth / 2;
|
||||
uint32_t const vph = height / 2;
|
||||
mMainView->setViewport ({ sidebar + 0, 0, vpw, vph });
|
||||
mDepthView->setViewport({ sidebar + int32_t(vpw), 0, vpw, vph });
|
||||
mGodView->setViewport ({ sidebar + int32_t(vpw), int32_t(vph), vpw, vph });
|
||||
mOrthoView->setViewport({ sidebar + 0, int32_t(vph), vpw, vph });
|
||||
} else {
|
||||
mMainView->setViewport({ sidebar, 0, mainWidth, height });
|
||||
}
|
||||
|
||||
@@ -896,6 +896,8 @@ int main(int argc, char** argv) {
|
||||
debug.getPropertyAddress<bool>("d.shadowmap.focus_shadowcasters"));
|
||||
ImGui::Checkbox("Disable light frustum alignment",
|
||||
debug.getPropertyAddress<bool>("d.shadowmap.disable_light_frustum_align"));
|
||||
ImGui::Checkbox("Depth clamp",
|
||||
debug.getPropertyAddress<bool>("d.shadowmap.depth_clamp"));
|
||||
|
||||
bool debugDirectionalShadowmap;
|
||||
if (debug.getProperty("d.shadowmap.debug_directional_shadowmap",
|
||||
|
||||
Reference in New Issue
Block a user