diff --git a/libs/filamat/include/filamat/MaterialBuilder.h b/libs/filamat/include/filamat/MaterialBuilder.h index bd586fe92e..f3e2080df6 100644 --- a/libs/filamat/include/filamat/MaterialBuilder.h +++ b/libs/filamat/include/filamat/MaterialBuilder.h @@ -243,6 +243,7 @@ public: using Precision = filament::backend::Precision; using CullingMode = filament::backend::CullingMode; using FeatureLevel = filament::backend::FeatureLevel; + using StereoscopicType = filament::backend::StereoscopicType; enum class VariableQualifier : uint8_t { OUT @@ -521,6 +522,9 @@ public: //! Specifies how transparent objects should be rendered (default is DEFAULT). MaterialBuilder& transparencyMode(TransparencyMode mode) noexcept; + //! Specify the stereoscopic type (default is INSTANCED) + MaterialBuilder& stereoscopicType(StereoscopicType stereoscopicType) noexcept; + /** * Enable / disable custom surface shading. Custom surface shading requires the LIT * shading model. In addition, the following function must be defined in the fragment @@ -829,6 +833,7 @@ private: Interpolation mInterpolation = Interpolation::SMOOTH; VertexDomain mVertexDomain = VertexDomain::OBJECT; TransparencyMode mTransparencyMode = TransparencyMode::DEFAULT; + StereoscopicType mStereoscopicType = StereoscopicType::INSTANCED; filament::AttributeBitset mRequiredAttributes; diff --git a/libs/filamat/src/MaterialBuilder.cpp b/libs/filamat/src/MaterialBuilder.cpp index 492c898c69..f022c0a983 100644 --- a/libs/filamat/src/MaterialBuilder.cpp +++ b/libs/filamat/src/MaterialBuilder.cpp @@ -498,6 +498,11 @@ MaterialBuilder& MaterialBuilder::transparencyMode(TransparencyMode mode) noexce return *this; } +MaterialBuilder& MaterialBuilder::stereoscopicType(StereoscopicType stereoscopicType) noexcept { + mStereoscopicType = stereoscopicType; + return *this; +} + MaterialBuilder& MaterialBuilder::reflectionMode(ReflectionMode mode) noexcept { mReflectionMode = mode; return *this; @@ -632,6 +637,7 @@ void MaterialBuilder::prepareToBuild(MaterialInfo& info) noexcept { info.vertexDomainDeviceJittered = mVertexDomainDeviceJittered; info.featureLevel = mFeatureLevel; info.groupSize = mGroupSize; + info.stereoscopicType = mStereoscopicType; // This is determined via static analysis of the glsl after prepareToBuild(). info.userMaterialHasCustomDepth = false; diff --git a/libs/filamat/src/shaders/CodeGenerator.cpp b/libs/filamat/src/shaders/CodeGenerator.cpp index a739e726e9..f713411e8b 100644 --- a/libs/filamat/src/shaders/CodeGenerator.cpp +++ b/libs/filamat/src/shaders/CodeGenerator.cpp @@ -181,6 +181,15 @@ utils::io::sstream& CodeGenerator::generateProlog(utils::io::sstream& out, Shade } generateDefine(out, "FILAMENT_EFFECTIVE_VERSION", effective_version); + switch (material.stereoscopicType) { + case StereoscopicType::INSTANCED: + generateDefine(out, "FILAMENT_STEREO_INSTANCED", true); + break; + case StereoscopicType::MULTIVIEW: + generateDefine(out, "FILAMENT_STEREO_MULTIVIEW", true); + break; + } + if (stage == ShaderStage::VERTEX) { CodeGenerator::generateDefine(out, "FLIP_UV_ATTRIBUTE", material.flipUV); CodeGenerator::generateDefine(out, "LEGACY_MORPHING", material.useLegacyMorphing); diff --git a/libs/filamat/src/shaders/MaterialInfo.h b/libs/filamat/src/shaders/MaterialInfo.h index b12863cede..5ede9f8c1f 100644 --- a/libs/filamat/src/shaders/MaterialInfo.h +++ b/libs/filamat/src/shaders/MaterialInfo.h @@ -68,6 +68,7 @@ struct UTILS_PUBLIC MaterialInfo { filament::SamplerBindingMap samplerBindings; filament::ShaderQuality quality; filament::backend::FeatureLevel featureLevel; + filament::backend::StereoscopicType stereoscopicType; filament::math::uint3 groupSize; using BufferContainer = utils::FixedCapacityVector; diff --git a/shaders/src/common_getters.glsl b/shaders/src/common_getters.glsl index eaa2521d85..a2bbebe4f8 100644 --- a/shaders/src/common_getters.glsl +++ b/shaders/src/common_getters.glsl @@ -25,8 +25,12 @@ highp mat4 getViewFromClipMatrix() { /** @public-api */ highp mat4 getClipFromWorldMatrix() { #if defined(VARIANT_HAS_STEREO) +#if defined(FILAMENT_STEREO_INSTANCED) int eye = instance_index % CONFIG_STEREO_EYE_COUNT; return frameUniforms.clipFromWorldMatrix[eye]; +#elif defined(FILAMENT_STEREO_MULTIVIEW) + return frameUniforms.clipFromWorldMatrix[gl_ViewID_OVR]; +#endif #else return frameUniforms.clipFromWorldMatrix[0]; #endif diff --git a/shaders/src/main.vs b/shaders/src/main.vs index 5ef0ebbe20..bbb9230fc8 100644 --- a/shaders/src/main.vs +++ b/shaders/src/main.vs @@ -23,7 +23,7 @@ void main() { logical_instance_index = instance_index; #endif -#if defined(VARIANT_HAS_STEREO) +#if defined(VARIANT_HAS_STEREO) && defined(FILAMENT_STEREO_INSTANCED) #if !defined(FILAMENT_HAS_FEATURE_INSTANCING) #error Instanced stereo not supported at this feature level #endif @@ -215,7 +215,7 @@ void main() { // this must happen before we compensate for vulkan below vertex_position = position; -#if defined(VARIANT_HAS_STEREO) +#if defined(VARIANT_HAS_STEREO) && defined(FILAMENT_STEREO_INSTANCED) // We're transforming a vertex whose x coordinate is within the range (-w to w). // To move it to the correct portion of the viewport, we need to modify the x coordinate. // It's important to do this after computing vertex_position. @@ -253,7 +253,7 @@ void main() { // some PowerVR drivers crash when gl_Position is written more than once gl_Position = position; -#if defined(VARIANT_HAS_STEREO) +#if defined(VARIANT_HAS_STEREO) && defined(FILAMENT_STEREO_INSTANCED) // Fragment shaders filter out the stereo variant, so we need to set instance_index here. instance_index = logical_instance_index; #endif diff --git a/shaders/src/varyings.glsl b/shaders/src/varyings.glsl index a7a48a302f..a0478838de 100644 --- a/shaders/src/varyings.glsl +++ b/shaders/src/varyings.glsl @@ -34,7 +34,7 @@ LAYOUT_LOCATION(11) VARYING highp vec4 vertex_lightSpacePosition; // Note that fragColor is an output and is not declared here; see main.fs and depth_main.fs -#if defined(VARIANT_HAS_STEREO) +#if defined(VARIANT_HAS_STEREO) && defined(FILAMENT_STEREO_INSTANCED) #if defined(GL_ES) && defined(FILAMENT_GLSLANG) // On ES, gl_ClipDistance is not a built-in, so we have to rely on EXT_clip_cull_distance // However, this extension is not supported by glslang, so we instead write to diff --git a/tools/matc/src/matc/ParametersProcessor.cpp b/tools/matc/src/matc/ParametersProcessor.cpp index 50d3ab7420..eacf7f24aa 100644 --- a/tools/matc/src/matc/ParametersProcessor.cpp +++ b/tools/matc/src/matc/ParametersProcessor.cpp @@ -796,6 +796,20 @@ static bool processGroupSizes(MaterialBuilder& builder, const JsonishValue& v) { return true; } +static bool processStereoscopicType(MaterialBuilder& builder, const JsonishValue& value) { + static const std::unordered_map strToEnum{ + { "instanced", MaterialBuilder::StereoscopicType::INSTANCED }, + { "multiview", MaterialBuilder::StereoscopicType::MULTIVIEW }, + }; + auto jsonString = value.toJsonString(); + if (!isStringValidEnum(strToEnum, jsonString->getString())) { + return logEnumIssue("stereoscopicType", *jsonString, strToEnum); + } + + builder.stereoscopicType(stringToEnum(strToEnum, jsonString->getString())); + return true; +} + static bool processOutput(MaterialBuilder& builder, const JsonishObject& jsonObject) noexcept { const JsonishValue* nameValue = jsonObject.getValue("name"); @@ -1214,6 +1228,7 @@ ParametersProcessor::ParametersProcessor() { mParameters["customSurfaceShading"] = { &processCustomSurfaceShading, Type::BOOL }; mParameters["featureLevel"] = { &processFeatureLevel, Type::NUMBER }; mParameters["groupSize"] = { &processGroupSizes, Type::ARRAY }; + mParameters["stereoscopicType"] = { &processStereoscopicType, Type::STRING }; } bool ParametersProcessor::process(MaterialBuilder& builder, const JsonishObject& jsonObject) {