diff --git a/CMakeLists.txt b/CMakeLists.txt index b33bbd73a2..300367a277 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -49,6 +49,8 @@ option(FILAMENT_ENABLE_COVERAGE "Enable LLVM code coverage" OFF) option(FILAMENT_ENABLE_FEATURE_LEVEL_0 "Enable Feature Level 0" ON) +option(FILAMENT_ENABLE_MULTIVIEW "Enable multiview for Filament" OFF) + option(FILAMENT_SUPPORTS_OSMESA "Enable OSMesa (headless GL context) for Filament" OFF) option(FILAMENT_ENABLE_FGVIEWER "Enable the frame graph viewer" OFF) @@ -605,6 +607,23 @@ else() option(FILAMENT_DISABLE_MATOPT "Disable material optimizations" ON) endif() +# This only affects the prebuilt shader files in gltfio and samples, not filament library. +# The value can be either "instanced", "multiview", or "none" +set(FILAMENT_SAMPLES_STEREO_TYPE "none" CACHE STRING + "Stereoscopic type that shader files in gltfio and samples are built for." +) +string(TOLOWER "${FILAMENT_SAMPLES_STEREO_TYPE}" FILAMENT_SAMPLES_STEREO_TYPE) +if (NOT FILAMENT_SAMPLES_STEREO_TYPE STREQUAL "instanced" + AND NOT FILAMENT_SAMPLES_STEREO_TYPE STREQUAL "multiview" + AND NOT FILAMENT_SAMPLES_STEREO_TYPE STREQUAL "none") + message(FATAL_ERROR "Invalid stereo type: \"${FILAMENT_SAMPLES_STEREO_TYPE}\" choose either \"instanced\", \"multiview\", or \"none\" ") +endif () + +# Compiling samples for multiview implies enabling multiview feature as well. +if (FILAMENT_SAMPLES_STEREO_TYPE STREQUAL "multiview") + set(FILAMENT_ENABLE_MULTIVIEW ON) +endif () + # Define backend flag for debug only if (CMAKE_BUILD_TYPE STREQUAL "Debug" AND NOT FILAMENT_BACKEND_DEBUG_FLAG STREQUAL "") add_definitions(-DFILAMENT_BACKEND_DEBUG_FLAG=${FILAMENT_BACKEND_DEBUG_FLAG}) diff --git a/build.sh b/build.sh index d5fe18f47c..ecabc0fb1f 100755 --- a/build.sh +++ b/build.sh @@ -214,6 +214,8 @@ ENABLE_PERFETTO="" BACKEND_DEBUG_FLAG_OPTION="" +STEREOSCOPIC_OPTION="" + OSMESA_OPTION="" IOS_BUILD_SIMULATOR=false @@ -314,6 +316,7 @@ function build_desktop_target { ${ASAN_UBSAN_OPTION} \ ${COVERAGE_OPTION} \ ${BACKEND_DEBUG_FLAG_OPTION} \ + ${STEREOSCOPIC_OPTION} \ ${OSMESA_OPTION} \ ${architectures} \ ../.. @@ -452,6 +455,7 @@ function build_android_target { ${VULKAN_ANDROID_OPTION} \ ${WEBGPU_OPTION} \ ${BACKEND_DEBUG_FLAG_OPTION} \ + ${STEREOSCOPIC_OPTION} \ ${ENABLE_PERFETTO} \ ../.. ln -sf "out/cmake-android-${lc_target}-${arch}/compile_commands.json" \ @@ -693,6 +697,7 @@ function build_ios_target { ${WEBGPU_OPTION} \ ${MATDBG_OPTION} \ ${MATOPT_OPTION} \ + ${STEREOSCOPIC_OPTION} \ ../.. ln -sf "out/cmake-ios-${lc_target}-${arch}/compile_commands.json" \ ../../compile_commands.json @@ -1006,6 +1011,20 @@ while getopts ":hacCfgimp:q:uvWslwedtk:bVx:S:X:Py:" opt; do ;; x) BACKEND_DEBUG_FLAG_OPTION="-DFILAMENT_BACKEND_DEBUG_FLAG=${OPTARG}" ;; + S) case $(echo "${OPTARG}" | tr '[:upper:]' '[:lower:]') in + instanced) + STEREOSCOPIC_OPTION="-DFILAMENT_SAMPLES_STEREO_TYPE=instanced" + ;; + multiview) + STEREOSCOPIC_OPTION="-DFILAMENT_SAMPLES_STEREO_TYPE=multiview" + ;; + *) + echo "Unknown stereoscopic type ${OPTARG}" + echo "Type must be one of [instanced|multiview]" + echo "" + exit 1 + esac + ;; X) OSMESA_OPTION="-DFILAMENT_OSMESA_PATH=${OPTARG}" ;; y) diff --git a/filament/CMakeLists.txt b/filament/CMakeLists.txt index 5547e93e1c..f82ad0528a 100644 --- a/filament/CMakeLists.txt +++ b/filament/CMakeLists.txt @@ -314,6 +314,12 @@ set(MATERIAL_FL0_SRCS src/materials/skybox.mat ) +set(MATERIAL_MULTIVIEW_SRCS + src/materials/clearDepth.mat + src/materials/defaultMaterial.mat + src/materials/skybox.mat +) + # ================================================================================================== # Configuration # ================================================================================================== @@ -338,6 +344,11 @@ if (FILAMENT_ENABLE_FEATURE_LEVEL_0) add_definitions(-DFILAMENT_ENABLE_FEATURE_LEVEL_0) endif() +# Whether to include MULTIVIEW materials. +if (FILAMENT_ENABLE_MULTIVIEW) + add_definitions(-DFILAMENT_ENABLE_MULTIVIEW) +endif() + # Whether to force the profiling mode. if (FILAMENT_FORCE_PROFILING_MODE) add_definitions(-DFILAMENT_FORCE_PROFILING_MODE) @@ -428,6 +439,21 @@ foreach(mat_dir ${MATERIAL_DIRS}) list(APPEND FILAMAT_FILES_FOR_GROUP ${output_path_fl0}) list(APPEND FILAMAT_TARGETS_FOR_GROUP ${output_path_fl0}) endif() + + # --- Multiview variant --- + list(FIND MATERIAL_MULTIVIEW_SRCS ${mat_src} index) + if (${index} GREATER -1 AND FILAMENT_ENABLE_MULTIVIEW) + string(REGEX REPLACE "[.]filamat$" "_multiview.filamat" output_path_multiview ${output_path}) + add_custom_command( + OUTPUT ${output_path_multiview} + COMMAND matc ${MATC_BASE_FLAGS} -PstereoscopicType=multiview -o ${output_path_multiview} ${fullname} + MAIN_DEPENDENCY ${fullname} + DEPENDS matc + COMMENT "Compiling material ${fullname} (Multiview)" + ) + list(APPEND FILAMAT_FILES_FOR_GROUP ${output_path_multiview}) + list(APPEND FILAMAT_TARGETS_FOR_GROUP ${output_path_multiview}) + endif() endforeach() # Generate a single resource file for the whole group diff --git a/filament/src/details/Engine.cpp b/filament/src/details/Engine.cpp index ca4d6f30ae..7da79f6b96 100644 --- a/filament/src/details/Engine.cpp +++ b/filament/src/details/Engine.cpp @@ -462,8 +462,22 @@ void FEngine::init() { #endif { FMaterial::DefaultMaterialBuilder defaultMaterialBuilder; - defaultMaterialBuilder.package( - MATERIALS_DEFAULTMATERIAL_DATA, MATERIALS_DEFAULTMATERIAL_SIZE); + switch (mConfig.stereoscopicType) { + case StereoscopicType::NONE: + case StereoscopicType::INSTANCED: + defaultMaterialBuilder.package( + MATERIALS_DEFAULTMATERIAL_DATA, MATERIALS_DEFAULTMATERIAL_SIZE); + break; + case StereoscopicType::MULTIVIEW: +#ifdef FILAMENT_ENABLE_MULTIVIEW + defaultMaterialBuilder.package( + MATERIALS_DEFAULTMATERIAL_MULTIVIEW_DATA, + MATERIALS_DEFAULTMATERIAL_MULTIVIEW_SIZE); +#else + assert_invariant(false); +#endif + break; + } mDefaultMaterial = downcast(defaultMaterialBuilder.build(*this)); } diff --git a/filament/src/details/Skybox.cpp b/filament/src/details/Skybox.cpp index de385c4292..c8dc171094 100644 --- a/filament/src/details/Skybox.cpp +++ b/filament/src/details/Skybox.cpp @@ -138,7 +138,20 @@ FMaterial const* FSkybox::createMaterial(FEngine& engine) { } else #endif { - builder.package(MATERIALS_SKYBOX_DATA, MATERIALS_SKYBOX_SIZE); + switch (engine.getConfig().stereoscopicType) { + case Engine::StereoscopicType::NONE: + case Engine::StereoscopicType::INSTANCED: + builder.package(MATERIALS_SKYBOX_DATA, MATERIALS_SKYBOX_SIZE); + break; + case Engine::StereoscopicType::MULTIVIEW: +#ifdef FILAMENT_ENABLE_MULTIVIEW + builder.package(MATERIALS_SKYBOX_MULTIVIEW_DATA, MATERIALS_SKYBOX_MULTIVIEW_SIZE); +#else + PANIC_POSTCONDITION("Multiview is enabled in the Engine, but this build has not " + "been compiled for multiview."); +#endif + break; + } } auto material = builder.build(engine); return downcast(material); diff --git a/libs/filagui/CMakeLists.txt b/libs/filagui/CMakeLists.txt index 68e1c4713e..87c4799ea7 100644 --- a/libs/filagui/CMakeLists.txt +++ b/libs/filagui/CMakeLists.txt @@ -40,13 +40,20 @@ endif() file(MAKE_DIRECTORY ${MATERIAL_DIR}) +set (MATC_FLAGS ${MATC_BASE_FLAGS}) +if (FILAMENT_SAMPLES_STEREO_TYPE STREQUAL "instanced") + set (MATC_FLAGS ${MATC_FLAGS} -PstereoscopicType=instanced) +elseif (FILAMENT_SAMPLES_STEREO_TYPE STREQUAL "multiview") + set (MATC_FLAGS ${MATC_FLAGS} -PstereoscopicType=multiview) +endif () + foreach (mat_src ${MATERIAL_SRCS}) get_filename_component(localname "${mat_src}" NAME_WE) get_filename_component(fullname "${mat_src}" ABSOLUTE) set(output_path "${MATERIAL_DIR}/${localname}.filamat") add_custom_command( OUTPUT ${output_path} - COMMAND matc ${MATC_BASE_FLAGS} -o ${output_path} ${fullname} + COMMAND matc ${MATC_FLAGS} -o ${output_path} ${fullname} DEPENDS ${mat_src} matc COMMENT "Compiling material ${mat_src} to ${output_path}" ) diff --git a/libs/filamat/include/filamat/MaterialBuilder.h b/libs/filamat/include/filamat/MaterialBuilder.h index 6f1e4eb239..e8b3ea7811 100644 --- a/libs/filamat/include/filamat/MaterialBuilder.h +++ b/libs/filamat/include/filamat/MaterialBuilder.h @@ -939,7 +939,7 @@ private: Interpolation mInterpolation = Interpolation::SMOOTH; VertexDomain mVertexDomain = VertexDomain::OBJECT; TransparencyMode mTransparencyMode = TransparencyMode::DEFAULT; - StereoscopicType mStereoscopicType = StereoscopicType::MULTIVIEW; + StereoscopicType mStereoscopicType = StereoscopicType::INSTANCED; uint8_t mStereoscopicEyeCount = 2; filament::AttributeBitset mRequiredAttributes; diff --git a/libs/filamentapp/CMakeLists.txt b/libs/filamentapp/CMakeLists.txt index 129e877739..265930bfad 100644 --- a/libs/filamentapp/CMakeLists.txt +++ b/libs/filamentapp/CMakeLists.txt @@ -114,13 +114,22 @@ file(MAKE_DIRECTORY ${RESOURCE_DIR}) set(RESOURCE_BINS) +set (MATC_FLAGS ${MATC_BASE_FLAGS}) +if (FILAMENT_SAMPLES_STEREO_TYPE STREQUAL "instanced") + set (MATC_FLAGS ${MATC_FLAGS} -PstereoscopicType=instanced) + add_definitions(-DFILAMENT_SAMPLES_STEREO_TYPE_INSTANCED) +elseif (FILAMENT_SAMPLES_STEREO_TYPE STREQUAL "multiview") + set (MATC_FLAGS ${MATC_FLAGS} -PstereoscopicType=multiview) + add_definitions(-DFILAMENT_SAMPLES_STEREO_TYPE_MULTIVIEW) +endif () + foreach (mat_src ${MATERIAL_SRCS}) get_filename_component(localname "${mat_src}" NAME_WE) get_filename_component(fullname "${mat_src}" ABSOLUTE) set(output_path "${MATERIAL_DIR}/${localname}.filamat") add_custom_command( OUTPUT ${output_path} - COMMAND matc ${MATC_BASE_FLAGS} -o ${output_path} ${fullname} + COMMAND matc ${MATC_FLAGS} -o ${output_path} ${fullname} MAIN_DEPENDENCY ${mat_src} DEPENDS matc COMMENT "Compiling material ${mat_src} to ${output_path}" diff --git a/libs/filamentapp/src/FilamentApp.cpp b/libs/filamentapp/src/FilamentApp.cpp index 6d58c50cdc..269952cb5d 100644 --- a/libs/filamentapp/src/FilamentApp.cpp +++ b/libs/filamentapp/src/FilamentApp.cpp @@ -741,7 +741,13 @@ FilamentApp::Window::Window(FilamentApp* filamentApp, Engine::Config engineConfig = {}; engineConfig.stereoscopicEyeCount = config.stereoscopicEyeCount; +#if defined(FILAMENT_SAMPLES_STEREO_TYPE_INSTANCED) + engineConfig.stereoscopicType = Engine::StereoscopicType::INSTANCED; +#elif defined (FILAMENT_SAMPLES_STEREO_TYPE_MULTIVIEW) engineConfig.stereoscopicType = Engine::StereoscopicType::MULTIVIEW; +#else + engineConfig.stereoscopicType = Engine::StereoscopicType::NONE; +#endif backend::Platform* platform = nullptr; #if defined(FILAMENT_DRIVER_SUPPORTS_VULKAN) diff --git a/libs/gltfio/CMakeLists.txt b/libs/gltfio/CMakeLists.txt index 601cf474b4..0ab7c96119 100644 --- a/libs/gltfio/CMakeLists.txt +++ b/libs/gltfio/CMakeLists.txt @@ -79,6 +79,13 @@ set(TRANSPARENCY default) set(UBERZ_OUTPUT_PATH "${RESOURCE_DIR}/default.uberz") +set (MATC_FLAGS ${MATC_BASE_FLAGS}) +if (FILAMENT_SAMPLES_STEREO_TYPE STREQUAL "instanced") + set (MATC_FLAGS ${MATC_FLAGS} -PstereoscopicType=instanced) +elseif (FILAMENT_SAMPLES_STEREO_TYPE STREQUAL "multiview") + set (MATC_FLAGS ${MATC_FLAGS} -PstereoscopicType=multiview) +endif () + function(build_ubershader NAME SRC SHADINGMODEL BLENDING) set(DEST "${RESOURCE_DIR}/${NAME}") configure_file(materials/${SRC}.mat.in "${DEST}.mat" COPYONLY) @@ -95,7 +102,7 @@ function(build_ubershader NAME SRC SHADINGMODEL BLENDING) add_custom_command( OUTPUT "${NAME}.filamat" - COMMAND matc ${MATC_BASE_FLAGS} ${TEMPLATE_ARGS} -o "${NAME}.filamat" "${NAME}.mat" + COMMAND matc ${MATC_FLAGS} ${TEMPLATE_ARGS} -o "${NAME}.filamat" "${NAME}.mat" DEPENDS matc "${DEST}.mat" WORKING_DIRECTORY ${RESOURCE_DIR} COMMENT "Compiling material ${NAME}") diff --git a/libs/viewer/CMakeLists.txt b/libs/viewer/CMakeLists.txt index a421612929..d725c9c568 100644 --- a/libs/viewer/CMakeLists.txt +++ b/libs/viewer/CMakeLists.txt @@ -34,6 +34,12 @@ target_link_libraries(${TARGET} PUBLIC imgui filament gltfio_core filagui jsmn c target_include_directories(${TARGET} PUBLIC ${PUBLIC_HDR_DIR}) set_target_properties(${TARGET} PROPERTIES FOLDER Libs) +if (FILAMENT_SAMPLES_STEREO_TYPE STREQUAL "instanced") + add_definitions(-DFILAMENT_SAMPLES_STEREO_TYPE_INSTANCED) +elseif (FILAMENT_SAMPLES_STEREO_TYPE STREQUAL "multiview") + add_definitions(-DFILAMENT_SAMPLES_STEREO_TYPE_MULTIVIEW) +endif () + # ================================================================================================== # Compiler flags # ================================================================================================== diff --git a/libs/viewer/src/ViewerGui.cpp b/libs/viewer/src/ViewerGui.cpp index 78f72f9f19..b8f041c562 100644 --- a/libs/viewer/src/ViewerGui.cpp +++ b/libs/viewer/src/ViewerGui.cpp @@ -1153,13 +1153,15 @@ void ViewerGui::updateUserInterface() { ImGui::ListBox("Cameras", &mCurrentCamera, cstrings.data(), cstrings.size()); } +#if defined(FILAMENT_SAMPLES_STEREO_TYPE_INSTANCED) \ + || defined(FILAMENT_SAMPLES_STEREO_TYPE_MULTIVIEW) ImGui::Checkbox("Stereo mode", &mSettings.view.stereoscopicOptions.enabled); - +#if defined(FILAMENT_SAMPLES_STEREO_TYPE_MULTIVIEW) ImGui::Indent(); ImGui::Checkbox("Combine Multiview Images", debug.getPropertyAddress("d.stereo.combine_multiview_images")); ImGui::Unindent(); - +#endif ImGui::SliderFloat("Ocular distance", &mSettings.camera.eyeOcularDistance, 0.0f, 1.0f); float toeInDegrees = mSettings.camera.eyeToeIn / f::PI * 180.0f; @@ -1167,6 +1169,7 @@ void ViewerGui::updateUserInterface() { mSettings.camera.eyeToeIn = toeInDegrees / 180.0f * f::PI; ImGui::Unindent(); +#endif } if (ImGui::CollapsingHeader("Debug Options")) { diff --git a/samples/CMakeLists.txt b/samples/CMakeLists.txt index cc54c67d7d..9015104988 100644 --- a/samples/CMakeLists.txt +++ b/samples/CMakeLists.txt @@ -54,13 +54,22 @@ endif() file(MAKE_DIRECTORY ${MATERIAL_DIR}) +set (MATC_FLAGS ${MATC_BASE_FLAGS}) +if (FILAMENT_SAMPLES_STEREO_TYPE STREQUAL "instanced") + set (MATC_FLAGS ${MATC_FLAGS} -PstereoscopicType=instanced) + add_definitions(-DFILAMENT_SAMPLES_STEREO_TYPE_INSTANCED) +elseif (FILAMENT_SAMPLES_STEREO_TYPE STREQUAL "multiview") + set (MATC_FLAGS ${MATC_FLAGS} -PstereoscopicType=multiview) + add_definitions(-DFILAMENT_SAMPLES_STEREO_TYPE_MULTIVIEW) +endif () + foreach (mat_src ${MATERIAL_SRCS}) get_filename_component(localname "${mat_src}" NAME_WE) get_filename_component(fullname "${mat_src}" ABSOLUTE) set(output_path "${MATERIAL_DIR}/${localname}.filamat") add_custom_command( OUTPUT ${output_path} - COMMAND matc ${MATC_BASE_FLAGS} -o ${output_path} ${fullname} + COMMAND matc ${MATC_FLAGS} -o ${output_path} ${fullname} MAIN_DEPENDENCY ${mat_src} DEPENDS matc COMMENT "Compiling material ${mat_src} to ${output_path}" diff --git a/samples/hellostereo.cpp b/samples/hellostereo.cpp index 86dec87ee4..cf81e192ba 100644 --- a/samples/hellostereo.cpp +++ b/samples/hellostereo.cpp @@ -160,6 +160,12 @@ static int handleCommandLineArguments(int argc, char* argv[], App* app) { } int main(int argc, char** argv) { + +#if !defined(FILAMENT_SAMPLES_STEREO_TYPE_MULTIVIEW) + std::cerr << "This sample only works with multiview enabled.\n"; + exit(1); +#endif + App app{}; app.config.title = "stereoscopic rendering"; handleCommandLineArguments(argc, argv, &app);