diff --git a/Dev/Plugin/Assets/Effekseer/External/HDRP/EffekseerRendererHDRP.cs b/Dev/Plugin/Assets/Effekseer/External/HDRP/EffekseerRendererHDRP.cs index 35ceaa75..8f4d178d 100644 --- a/Dev/Plugin/Assets/Effekseer/External/HDRP/EffekseerRendererHDRP.cs +++ b/Dev/Plugin/Assets/Effekseer/External/HDRP/EffekseerRendererHDRP.cs @@ -51,19 +51,28 @@ bool TryPrepareRender(RTHandle colorBuffer, RTHandle depthBuffer, HDCamera hdCam prop.depthTargetRenderTexture = depthBuffer; prop.renderFeature = Effekseer.Internal.RenderFeature.HDRP; - // TODO : It needs to support VR and override - prop.ActualScreenSize = new Vector2Int(hdCamera.actualWidth, hdCamera.actualHeight); - prop.SourceViewport = hdCamera.camera.pixelRect; -#if UNITY_6000_0_OR_NEWER - // HDRP keeps the full-resolution RT allocated and shrinks the active viewport when - // dynamic resolution is enabled, so keep the render viewport and the source - // sampling viewport separate. - prop.Viewport = new Rect(0, 0, hdCamera.actualWidth, hdCamera.actualHeight); -#else - prop.Viewport = new Rect(0, 0, hdCamera.camera.pixelRect.width, hdCamera.camera.pixelRect.height); -#endif - - prop.colorTargetDescriptor = new UnityEngine.RenderTextureDescriptor(colorRT.width, colorRT.height, colorRT.format, 0, colorRT.mipmapCount); + // HDRP-WA-DRS-001 (English): HDRP 14-17 keep camera RTHandles at their maximum allocation + // while Dynamic Resolution changes only the active viewport. camera.pixelRect is the + // unscaled GameView rectangle and copying that area also samples unused RTHandle pixels. + // Use the camera color RTHandle's current viewport for target binding and source sampling. + // Remove this only when HDRP exposes a camera color descriptor whose size is the active + // viewport rather than the backing allocation. + // HDRP-WA-DRS-001 (日本語): HDRP 14-17 は Camera RTHandle を最大サイズのまま確保し、 + // Dynamic Resolution では有効 Viewport のみを変更します。camera.pixelRect は縮小前の + // GameView 領域なので、そのままコピーすると RTHandle の未使用領域まで参照します。 + // Target の設定とコピー元の Sampling には Camera Color RTHandle の現在の Viewport を + // 使用します。HDRP が確保サイズではなく有効 Viewport サイズの Camera Color Descriptor を + // 提供するようになった場合のみ削除してください。 + var activeViewportSize = colorBuffer.GetScaledSize(colorBuffer.rtHandleProperties.currentViewportSize); + activeViewportSize.x = Mathf.Clamp(activeViewportSize.x, 1, colorRT.width); + activeViewportSize.y = Mathf.Clamp(activeViewportSize.y, 1, colorRT.height); + prop.ActualScreenSize = activeViewportSize; + prop.SourceViewport = new Rect(0, 0, activeViewportSize.x, activeViewportSize.y); + prop.Viewport = new Rect(0, 0, activeViewportSize.x, activeViewportSize.y); + + prop.colorTargetDescriptor = EffekseerRenderTargetDescriptorUtils.CreateTemporaryColorDescriptor( + colorRT, hdCamera.camera); + prop.colorTargetDescriptor.depthBufferBits = 0; prop.colorTargetDescriptor.msaaSamples = hdCamera.msaaSamples == MSAASamples.None ? 1 : 2; prop.isRequiredToChangeViewport = true; return true; @@ -81,7 +90,8 @@ void Execute(RTHandle colorBuffer, RTHandle depthBuffer, CommandBuffer cmd, HDCa return; } - EffekseerSystem.Instance.renderer.Render(hdCamera.camera, LayerMask.value, prop, cmd, true, blitter); + EffekseerRenderCoordinator.Render(EffekseerSystem.Instance.renderer, + new EffekseerRenderFrameInput(hdCamera.camera, LayerMask.value, prop, cmd, true, blitter)); } protected override void Execute(CustomPassContext ctx) diff --git a/Dev/Plugin/Assets/Effekseer/External/PostProcessing/PostProcessingStackEffekseer.cs b/Dev/Plugin/Assets/Effekseer/External/PostProcessing/PostProcessingStackEffekseer.cs index bb6eba86..22b00934 100644 --- a/Dev/Plugin/Assets/Effekseer/External/PostProcessing/PostProcessingStackEffekseer.cs +++ b/Dev/Plugin/Assets/Effekseer/External/PostProcessing/PostProcessingStackEffekseer.cs @@ -64,14 +64,17 @@ public override void Render(PostProcessRenderContext context) context.command.Blit(context.source, depthIdentifer, grabDepthMat); - prop.colorTargetDescriptor = new RenderTextureDescriptor(context.width, context.height, context.sourceFormat); + prop.xrRendering = Effekseer.Internal.EffekseerRenderTargetDescriptorUtils.CanUseXREyeTextureDescriptor(context.camera); + prop.colorTargetDescriptor = Effekseer.Internal.EffekseerRenderTargetDescriptorUtils.CreatePostProcessingDescriptor( + context.camera, context.width, context.height, context.sourceFormat); prop.colorTargetIdentifier = context.destination; prop.depthTargetIdentifier = depthIdentifer; prop.renderFeature = Effekseer.Internal.RenderFeature.PostProcess; prop.canGrabDepth = true; context.command.SetRenderTarget(context.destination, depthIdentifer); - Effekseer.EffekseerSystem.Instance.renderer.Render(context.camera, int.MaxValue, prop, context.command, false, standardBlitter); + Effekseer.Internal.EffekseerRenderCoordinator.Render(Effekseer.EffekseerSystem.Instance.renderer, + new Effekseer.Internal.EffekseerRenderFrameInput(context.camera, int.MaxValue, prop, context.command, false, standardBlitter)); context.command.ReleaseTemporaryRT(propertyId); } diff --git a/Dev/Plugin/Assets/Effekseer/External/URP/EffekseerURPRasterCommandBuffer.cs b/Dev/Plugin/Assets/Effekseer/External/URP/EffekseerURPRasterCommandBuffer.cs new file mode 100644 index 00000000..971bcf24 --- /dev/null +++ b/Dev/Plugin/Assets/Effekseer/External/URP/EffekseerURPRasterCommandBuffer.cs @@ -0,0 +1,39 @@ +#if EFFEKSEER_URP_SUPPORT && UNITY_6000_0_OR_NEWER + +using System; +using Effekseer.Internal; +using UnityEngine; +using UnityEngine.Rendering; + +internal sealed class EffekseerURPRasterCommandBuffer : IEffekseerCommandBuffer +{ + readonly RasterCommandBuffer _commandBuffer; + + public EffekseerURPRasterCommandBuffer(RasterCommandBuffer commandBuffer) + { + _commandBuffer = commandBuffer; + } + + public void SetViewport(Rect viewport) + { + _commandBuffer.SetViewport(viewport); + } + + public void SetGlobalBuffer(string name, ComputeBuffer buffer) + { + _commandBuffer.SetGlobalBuffer(name, buffer); + } + + public void DrawProcedural(Matrix4x4 matrix, Material material, int shaderPass, MeshTopology topology, + int vertexCount, int instanceCount, MaterialPropertyBlock properties) + { + _commandBuffer.DrawProcedural(matrix, material, shaderPass, topology, vertexCount, instanceCount, properties); + } + + public void IssuePluginEvent(IntPtr callback, int eventId) + { + _commandBuffer.IssuePluginEvent(callback, eventId); + } +} + +#endif diff --git a/Dev/Plugin/Assets/Effekseer/External/URP/EffekseerURPRasterCommandBuffer.cs.meta b/Dev/Plugin/Assets/Effekseer/External/URP/EffekseerURPRasterCommandBuffer.cs.meta new file mode 100644 index 00000000..b8610edb --- /dev/null +++ b/Dev/Plugin/Assets/Effekseer/External/URP/EffekseerURPRasterCommandBuffer.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: a65a79a42bb347e4aa09f8047943e94b diff --git a/Dev/Plugin/Assets/Effekseer/External/URP/EffekseerURPRenderPassFeature.cs b/Dev/Plugin/Assets/Effekseer/External/URP/EffekseerURPRenderPassFeature.cs index 1b4d6d63..ad5fa639 100644 --- a/Dev/Plugin/Assets/Effekseer/External/URP/EffekseerURPRenderPassFeature.cs +++ b/Dev/Plugin/Assets/Effekseer/External/URP/EffekseerURPRenderPassFeature.cs @@ -14,23 +14,46 @@ public class UrpBlitter : IEffekseerBlitter { public void Blit(CommandBuffer cmd, RenderTargetIdentifier source, RenderTargetIdentifier dest, bool xrRendering) { + // XR-WA-003 (English): CommandBuffer.Blit is unsafe for XR and RenderGraph, so those + // paths use the SRP Blitter. Unity 2022.3-2023.2 non-XR keeps CommandBuffer.Blit because + // URP 16 SceneView can otherwise interpret editor target color channels incorrectly. + // Remove the legacy branch after all supported pre-Unity-6 SceneView formats are verified. + // XR-WA-003 (日本語): CommandBuffer.Blit はXR・RenderGraphでは安全でないためSRP Blitterを + // 使用します。一方Unity 2022.3-2023.2の非XRでは、URP 16 SceneViewのEditor Target形式で + // Color Channelの解釈が変わる場合があるためCommandBuffer.Blitを維持します。Unity 6未満の + // 全SceneView形式でSRP Blitterを検証できた場合のみLegacy分岐を削除してください。 +#if UNITY_6000_0_OR_NEWER + CoreUtils.SetRenderTarget(cmd, dest); + Blitter.BlitTexture(cmd, source, Vector2.one, Blitter.GetBlitMaterial(xrRendering ? TextureXR.dimension : TextureDimension.Tex2D), 0); +#else if (xrRendering) { CoreUtils.SetRenderTarget(cmd, dest); - // FIXME: Scaling is ignored. - // The interface should take RTHandle instead of RenderTargetIdentifier and use Blitter.BlitCameraTexture. - // However, this will cause issues in terms of compatibility with Built-in RP support. Blitter.BlitTexture(cmd, source, Vector2.one, Blitter.GetBlitMaterial(TextureXR.dimension), 0); } else { cmd.Blit(source, dest); } +#endif } public void Blit(CommandBuffer cmd, RenderTargetIdentifier source, RenderTargetIdentifier dest, Material material, bool xrRendering) { - cmd.Blit(source, dest, material); +#if UNITY_6000_0_OR_NEWER + CoreUtils.SetRenderTarget(cmd, dest); + Blitter.BlitTexture(cmd, source, Vector2.one, material, 0); +#else + if (xrRendering) + { + CoreUtils.SetRenderTarget(cmd, dest); + Blitter.BlitTexture(cmd, source, Vector2.one, material, 0); + } + else + { + cmd.Blit(source, dest, material); + } +#endif } public void SetRenderTarget(CommandBuffer cmd, RenderTargetIdentifier color, bool xrRendering) @@ -68,7 +91,7 @@ public void SetLayerMask(UnityEngine.LayerMask layerMask) bool IsValidCameraDepthTarget(RenderTargetIdentifier cameraDepthTarget) { - // HACK: When using URP, the depth might be either written to a DepthBuffer attached to + // XR-WA-007 (English): When using URP, the depth might be either written to a DepthBuffer attached to // - cameraColorTarget // OR // - cameraDepthTarget @@ -89,11 +112,17 @@ bool IsValidCameraDepthTarget(RenderTargetIdentifier cameraDepthTarget) // A RenderTargetIdentifier might point to a valid RenderTexture in many different ways // (including NameID or InstanceID), whether NameID or InstanceID is used to identify a valid // RenderTexture depends on the Unity Editor / URP package version. + // Remove this when every supported URP version provides an authoritative valid-depth-target API. + // XR-WA-007 (日本語): URP の有効な Depth は Camera Color 側または Camera Depth 側にあり、 + // Unity・URP・Camera Stack・MSAA・Depth Texture 設定により変わります。そのため Identifier の + // NameID / InstanceID から有効性を判定します。対応する全 URP 版で正式な有効 Depth Target API が + // 提供された場合のみ削除してください。 var identifierString = cameraDepthTarget.ToString(); return !identifierString.Contains("NameID -1") || !identifierString.Contains("InstanceID 0"); } - void PrepareRenderTargetProperty(RenderTargetProperty renderTargetProperty, RenderTextureDescriptor colorTargetDescriptor, bool requiresDepthTexture, bool xrRendering) + void PrepareRenderTargetProperty(RenderTargetProperty renderTargetProperty, RenderTextureDescriptor colorTargetDescriptor, + bool requiresDepthTexture, bool xrRendering) { renderTargetProperty.colorBufferID = null; renderTargetProperty.depthTargetIdentifier = null; @@ -113,6 +142,11 @@ void PrepareRenderTargetProperty(RenderTargetProperty renderTargetProperty, Rend renderTargetProperty.xrRendering = xrRendering; } + // Unity 6000.5 / URP 17.5 removed ScriptableRenderPass.Execute. Unity 6000.0-6000.4 + // still exposes it as an obsolete compatibility path, so keep it only for those versions. + // Unity 6000.5 / URP 17.5 では ScriptableRenderPass.Execute が削除されました。 + // Unity 6000.0-6000.4 では旧互換経路として残っているため、それらのバージョンまで定義します。 +#if !UNITY_6000_5_OR_NEWER #if UNITY_6000_0_OR_NEWER [Obsolete] #endif @@ -120,7 +154,8 @@ public override void Execute(ScriptableRenderContext context, ref UnityEngine.Re { if (Effekseer.EffekseerSystem.Instance == null) return; var xrRendering = renderingData.cameraData.xrRendering; - PrepareRenderTargetProperty(prop, renderingData.cameraData.cameraTargetDescriptor, renderingData.cameraData.requiresDepthTexture, xrRendering); + PrepareRenderTargetProperty(prop, renderingData.cameraData.cameraTargetDescriptor, + renderingData.cameraData.requiresDepthTexture, xrRendering); var renderer = renderingData.cameraData.renderer; prop.colorTargetIdentifier = renderer.cameraColorTargetHandle; @@ -140,10 +175,12 @@ public override void Execute(ScriptableRenderContext context, ref UnityEngine.Re } var cmd = CommandBufferPool.Get(RenderPassName); - Effekseer.EffekseerSystem.Instance.renderer.Render(renderingData.cameraData.camera, layerMask.value, prop, cmd, true, blitter); + EffekseerRenderCoordinator.Render(Effekseer.EffekseerSystem.Instance.renderer, + new EffekseerRenderFrameInput(renderingData.cameraData.camera, layerMask.value, prop, cmd, true, blitter)); context.ExecuteCommandBuffer(cmd); CommandBufferPool.Release(cmd); } +#endif #if UNITY_6000_0_OR_NEWER class PassData @@ -168,7 +205,8 @@ static void ExecuteRenderGraphPass(PassData passData, UnsafeGraphContext context var commandBuffer = CommandBufferHelpers.GetNativeCommandBuffer(context.cmd); passData.prop.colorTargetIdentifier = (RenderTargetIdentifier)passData.colorTexture; passData.prop.depthTargetIdentifier = passData.depthTexture.IsValid() ? (RenderTargetIdentifier)passData.depthTexture : (RenderTargetIdentifier?)null; - system.renderer.Render(passData.camera, passData.layerMask, passData.prop, commandBuffer, true, passData.blitter); + EffekseerRenderCoordinator.Render(system.renderer, + new EffekseerRenderFrameInput(passData.camera, passData.layerMask, passData.prop, commandBuffer, true, passData.blitter)); } static void ExecuteRasterRenderGraphPass(PassData passData, RasterGraphContext context) @@ -179,10 +217,10 @@ static void ExecuteRasterRenderGraphPass(PassData passData, RasterGraphContext c return; } - var commandBuffer = CommandBufferHelpers.GetNativeCommandBuffer(context.cmd); - passData.prop.colorTargetIdentifier = (RenderTargetIdentifier)passData.colorTexture; - passData.prop.depthTargetIdentifier = passData.depthTexture.IsValid() ? (RenderTargetIdentifier)passData.depthTexture : (RenderTargetIdentifier?)null; - system.renderer.Render(passData.camera, passData.layerMask, passData.prop, commandBuffer, true, passData.blitter, false); + EffekseerRenderCoordinator.RenderExternal(system.renderer, + new EffekseerRenderFrameInput(passData.camera, passData.layerMask, passData.prop, null, true, passData.blitter, + usesExternalCommands: true), + new EffekseerURPRasterCommandBuffer(context.cmd)); } bool CanUseRasterPass(UniversalCameraData cameraData) @@ -217,7 +255,8 @@ public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer passData.blitter = this.blitter; passData.colorTexture = colorTexture; passData.depthTexture = resourceData.activeDepthTexture; - PrepareRenderTargetProperty(passData.prop, cameraData.cameraTargetDescriptor, cameraData.requiresDepthTexture, xrRendering); + PrepareRenderTargetProperty(passData.prop, cameraData.cameraTargetDescriptor, + cameraData.requiresDepthTexture, xrRendering); builder.SetRenderAttachment(passData.colorTexture, 0, AccessFlags.ReadWrite); if (passData.depthTexture.IsValid()) @@ -244,7 +283,8 @@ public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer { builder.UseTexture(passData.depthTexture, AccessFlags.ReadWrite); } - PrepareRenderTargetProperty(passData.prop, cameraData.cameraTargetDescriptor, cameraData.requiresDepthTexture, xrRendering); + PrepareRenderTargetProperty(passData.prop, cameraData.cameraTargetDescriptor, + cameraData.requiresDepthTexture, xrRendering); builder.AllowPassCulling(false); builder.AllowGlobalStateModification(true); diff --git a/Dev/Plugin/Assets/Effekseer/Materials/EffekseerShaderAdDistortionPS.cginc b/Dev/Plugin/Assets/Effekseer/Materials/EffekseerShaderAdDistortionPS.cginc index 714fafb4..7b298af8 100644 --- a/Dev/Plugin/Assets/Effekseer/Materials/EffekseerShaderAdDistortionPS.cginc +++ b/Dev/Plugin/Assets/Effekseer/Materials/EffekseerShaderAdDistortionPS.cginc @@ -22,7 +22,17 @@ Texture2D _blendUVDistortionTex : register(t6); SamplerState sampler_blendUVDistortionTex : register(s6); #ifndef DISABLED_SOFT_PARTICLE +// XR-WA-002 (English): SPI/Multiview depth is a texture array and must use the current eye slice. +// XR-WA-002 (日本語): SPI/Multiview の深度は Texture Array のため現在の Eye Slice を参照します。 +// Remove only when Unity transparently binds and samples one texture type for every XR mode. +// Unity が全 XR モードで単一の Texture 型を透過的に Bind/Sample する場合のみ削除してください。 +#if defined(UNITY_STEREO_INSTANCING_ENABLED) || defined(UNITY_STEREO_MULTIVIEW_ENABLED) +Texture2DArray _depthTex : register(t7); +#define EFK_SAMPLE_DEPTH(uv) _depthTex.Sample(sampler_depthTex, float3(uv, unity_StereoEyeIndex)) +#else Texture2D _depthTex : register(t7); +#define EFK_SAMPLE_DEPTH(uv) _depthTex.Sample(sampler_depthTex, uv) +#endif SamplerState sampler_depthTex : register(s7); #endif @@ -132,7 +142,7 @@ float4 frag(const PS_Input Input) if (softParticleParam.w != 0.0f) { - float backgroundZ = _depthTex.Sample(sampler_depthTex, screenUV).x; + float backgroundZ = EFK_SAMPLE_DEPTH(screenUV).x; Output.a *= SoftParticle( backgroundZ, screenPos.z, diff --git a/Dev/Plugin/Assets/Effekseer/Materials/EffekseerShaderAdLitUnlitPS.cginc b/Dev/Plugin/Assets/Effekseer/Materials/EffekseerShaderAdLitUnlitPS.cginc index 6d9f363c..54a5778f 100644 --- a/Dev/Plugin/Assets/Effekseer/Materials/EffekseerShaderAdLitUnlitPS.cginc +++ b/Dev/Plugin/Assets/Effekseer/Materials/EffekseerShaderAdLitUnlitPS.cginc @@ -50,7 +50,17 @@ Texture2D _blendUVDistortionTex : register(t6); SamplerState sampler_blendUVDistortionTex : register(s6); #ifndef DISABLED_SOFT_PARTICLE +// XR-WA-002 (English): SPI/Multiview depth is a texture array and must use the current eye slice. +// XR-WA-002 (日本語): SPI/Multiview の深度は Texture Array のため現在の Eye Slice を参照します。 +// Remove only when Unity transparently binds and samples one texture type for every XR mode. +// Unity が全 XR モードで単一の Texture 型を透過的に Bind/Sample する場合のみ削除してください。 +#if defined(UNITY_STEREO_INSTANCING_ENABLED) || defined(UNITY_STEREO_MULTIVIEW_ENABLED) +Texture2DArray _depthTex : register(t7); +#define EFK_SAMPLE_DEPTH(uv) _depthTex.Sample(sampler_depthTex, float3(uv, unity_StereoEyeIndex)) +#else Texture2D _depthTex : register(t7); +#define EFK_SAMPLE_DEPTH(uv) _depthTex.Sample(sampler_depthTex, uv) +#endif SamplerState sampler_depthTex : register(s7); #endif @@ -75,7 +85,13 @@ Texture2D _blendUVDistortionTex : register(t5); SamplerState sampler_blendUVDistortionTex : register(s5); #ifndef DISABLED_SOFT_PARTICLE +#if defined(UNITY_STEREO_INSTANCING_ENABLED) || defined(UNITY_STEREO_MULTIVIEW_ENABLED) +Texture2DArray _depthTex : register(t6); +#define EFK_SAMPLE_DEPTH(uv) _depthTex.Sample(sampler_depthTex, float3(uv, unity_StereoEyeIndex)) +#else Texture2D _depthTex : register(t6); +#define EFK_SAMPLE_DEPTH(uv) _depthTex.Sample(sampler_depthTex, uv) +#endif SamplerState sampler_depthTex : register(s6); #endif @@ -103,6 +119,7 @@ struct PS_Input #ifndef DISABLED_SOFT_PARTICLE float4 PosP : TEXCOORD7; #endif + UNITY_VERTEX_OUTPUT_STEREO }; #include "EffekseerShaderAdCommonPS.cginc" @@ -112,6 +129,7 @@ struct PS_Input float4 frag(const PS_Input Input) : SV_Target { + UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(Input); bool convColorSpace = convertColorSpace != 0.0f; float4 fCameraFrontDirection = -float4(UNITY_MATRIX_V[2].xyz, 1.0); @@ -193,7 +211,7 @@ float4 frag(const PS_Input Input) if (softParticleParam.w != 0.0f) { - float backgroundZ = _depthTex.Sample(sampler_depthTex, screenUV).x; + float backgroundZ = EFK_SAMPLE_DEPTH(screenUV).x; Output.a *= SoftParticle( backgroundZ, screenPos.z, diff --git a/Dev/Plugin/Assets/Effekseer/Materials/EffekseerShaderDistortionPS.cginc b/Dev/Plugin/Assets/Effekseer/Materials/EffekseerShaderDistortionPS.cginc index 10c08666..26ef46c9 100644 --- a/Dev/Plugin/Assets/Effekseer/Materials/EffekseerShaderDistortionPS.cginc +++ b/Dev/Plugin/Assets/Effekseer/Materials/EffekseerShaderDistortionPS.cginc @@ -6,7 +6,17 @@ SamplerState sampler_colorTex : register(s0); UNITY_DECLARE_SCREENSPACE_TEXTURE(_backTex); #ifndef DISABLED_SOFT_PARTICLE +// XR-WA-002 (English): SPI/Multiview depth is a texture array and must use the current eye slice. +// XR-WA-002 (日本語): SPI/Multiview の深度は Texture Array のため現在の Eye Slice を参照します。 +// Remove only when Unity transparently binds and samples one texture type for every XR mode. +// Unity が全 XR モードで単一の Texture 型を透過的に Bind/Sample する場合のみ削除してください。 +#if defined(UNITY_STEREO_INSTANCING_ENABLED) || defined(UNITY_STEREO_MULTIVIEW_ENABLED) +Texture2DArray _depthTex : register(t2); +#define EFK_SAMPLE_DEPTH(uv) _depthTex.Sample(sampler_depthTex, float3(uv, unity_StereoEyeIndex)) +#else Texture2D _depthTex : register(t2); +#define EFK_SAMPLE_DEPTH(uv) _depthTex.Sample(sampler_depthTex, uv) +#endif SamplerState sampler_depthTex : register(s2); #endif @@ -78,7 +88,7 @@ float4 frag(const PS_Input Input) if (softParticleParam.w != 0.0f) { - float backgroundZ = _depthTex.Sample(sampler_depthTex, screenUV).x; + float backgroundZ = EFK_SAMPLE_DEPTH(screenUV).x; Output.a *= SoftParticle( backgroundZ, screenPos.z, diff --git a/Dev/Plugin/Assets/Effekseer/Materials/EffekseerShaderLitUnlitPS.cginc b/Dev/Plugin/Assets/Effekseer/Materials/EffekseerShaderLitUnlitPS.cginc index d7a3c7d4..824da13f 100644 --- a/Dev/Plugin/Assets/Effekseer/Materials/EffekseerShaderLitUnlitPS.cginc +++ b/Dev/Plugin/Assets/Effekseer/Materials/EffekseerShaderLitUnlitPS.cginc @@ -38,14 +38,30 @@ Texture2D _normalTex : register(t1); SamplerState sampler_normalTex : register(s1); #ifndef DISABLED_SOFT_PARTICLE +// XR-WA-002 (English): SPI/Multiview depth is a texture array and must use the current eye slice. +// XR-WA-002 (日本語): SPI/Multiview の深度は Texture Array のため現在の Eye Slice を参照します。 +// Remove only when Unity transparently binds and samples one texture type for every XR mode. +// Unity が全 XR モードで単一の Texture 型を透過的に Bind/Sample する場合のみ削除してください。 +#if defined(UNITY_STEREO_INSTANCING_ENABLED) || defined(UNITY_STEREO_MULTIVIEW_ENABLED) +Texture2DArray _depthTex : register(t2); +#define EFK_SAMPLE_DEPTH(uv) _depthTex.Sample(sampler_depthTex, float3(uv, unity_StereoEyeIndex)) +#else Texture2D _depthTex : register(t2); +#define EFK_SAMPLE_DEPTH(uv) _depthTex.Sample(sampler_depthTex, uv) +#endif SamplerState sampler_depthTex : register(s2); #endif #else #ifndef DISABLED_SOFT_PARTICLE +#if defined(UNITY_STEREO_INSTANCING_ENABLED) || defined(UNITY_STEREO_MULTIVIEW_ENABLED) +Texture2DArray _depthTex : register(t1); +#define EFK_SAMPLE_DEPTH(uv) _depthTex.Sample(sampler_depthTex, float3(uv, unity_StereoEyeIndex)) +#else Texture2D _depthTex : register(t1); +#define EFK_SAMPLE_DEPTH(uv) _depthTex.Sample(sampler_depthTex, uv) +#endif SamplerState sampler_depthTex : register(s1); #endif @@ -104,7 +120,7 @@ float4 frag(const PS_Input Input) if (softParticleParam.w != 0.0f) { - float backgroundZ = _depthTex.Sample(sampler_depthTex, screenUV).x; + float backgroundZ = EFK_SAMPLE_DEPTH(screenUV).x; Output.a *= SoftParticle( backgroundZ, screenPos.z, diff --git a/Dev/Plugin/Assets/Effekseer/Scripts/EffekseerRenderPath.cs b/Dev/Plugin/Assets/Effekseer/Scripts/EffekseerRenderPath.cs index e4d39466..f37c7ccc 100644 --- a/Dev/Plugin/Assets/Effekseer/Scripts/EffekseerRenderPath.cs +++ b/Dev/Plugin/Assets/Effekseer/Scripts/EffekseerRenderPath.cs @@ -10,11 +10,13 @@ internal class CameraWithMask { public Camera camera; public int mask = int.MaxValue; + public bool usesExternalCommands; - public CameraWithMask(Camera camera, int mask) + public CameraWithMask(Camera camera, int mask, bool usesExternalCommands = false) { this.camera = camera; this.mask = mask; + this.usesExternalCommands = usesExternalCommands; } public override bool Equals(object obj) @@ -29,12 +31,12 @@ public override bool Equals(object obj) public override int GetHashCode() { - return camera.GetHashCode() + mask.GetHashCode(); + return camera.GetHashCode() + mask.GetHashCode() + usesExternalCommands.GetHashCode(); } public static bool operator ==(CameraWithMask v1, CameraWithMask v2) { - return v1.camera == v2.camera && v1.mask == v2.mask; + return v1.camera == v2.camera && v1.mask == v2.mask && v1.usesExternalCommands == v2.usesExternalCommands; } public static bool operator !=(CameraWithMask v1, CameraWithMask v2) @@ -151,7 +153,7 @@ public void CleanUp() renderPaths.Clear(); } - public void UpdateRenderPath(bool disableCullingMask, Camera camera, int additionalMask, RenderTargetProperty renderTargetProperty, CommandBuffer targetCommandBuffer, bool isScriptable, IEffekseerBlitter blitter, CameraEvent cameraEvent, out T path, out int allEffectMask, out int cameraMask) + public void UpdateRenderPath(bool disableCullingMask, Camera camera, int additionalMask, RenderTargetProperty renderTargetProperty, CommandBuffer targetCommandBuffer, bool isScriptable, IEffekseerBlitter blitter, CameraEvent cameraEvent, out T path, out int allEffectMask, out int cameraMask, bool useExternalCommandBuffer = false) { path = null; @@ -180,6 +182,7 @@ public void UpdateRenderPath(bool disableCullingMask, Camera camera, int additio #endif cameraWithMaskKey.camera = camera; cameraWithMaskKey.mask = additionalMask; + cameraWithMaskKey.usesExternalCommands = targetCommandBuffer != null || useExternalCommandBuffer; // don't need to update because doesn't exists and need not to render if ((allEffectMask & cameraMask) == 0 && !renderPaths.ContainsKey(cameraWithMaskKey)) @@ -247,10 +250,10 @@ public void UpdateRenderPath(bool disableCullingMask, Camera camera, int additio } path = new T(); - path.Init(camera, cameraEvent, nextRenderID, targetCommandBuffer != null, isScriptable); + path.Init(camera, cameraEvent, nextRenderID, targetCommandBuffer != null || useExternalCommandBuffer, isScriptable); var stereoRenderingType = (camera.stereoEnabled) ? StereoRendererUtil.GetStereoRenderingType() : StereoRendererUtil.StereoRenderingTypes.None; path.ResetParameters(EffekseerRendererUtils.IsDistortionEnabled, EffekseerRendererUtils.IsDepthEnabled, renderTargetProperty, blitter, stereoRenderingType); - renderPaths.Add(new CameraWithMask(camera, additionalMask), path); + renderPaths.Add(new CameraWithMask(camera, additionalMask, targetCommandBuffer != null || useExternalCommandBuffer), path); nextRenderID = (nextRenderID + 1) % EffekseerRendererUtils.RenderIDCount; } diff --git a/Dev/Plugin/Assets/Effekseer/Scripts/EffekseerRenderer.cs b/Dev/Plugin/Assets/Effekseer/Scripts/EffekseerRenderer.cs index d220a7b7..7a92aa51 100644 --- a/Dev/Plugin/Assets/Effekseer/Scripts/EffekseerRenderer.cs +++ b/Dev/Plugin/Assets/Effekseer/Scripts/EffekseerRenderer.cs @@ -20,7 +20,9 @@ public static void SetupDepthBuffer(ref DepthRenderTexture depthRenderTexure, bo { var targetSize = BackgroundRenderTexture.GetRequiredSize(camera, renderTargetProperty); - depthRenderTexure = new DepthRenderTexture(targetSize.x, targetSize.y, renderTargetProperty); + depthRenderTexure = new DepthRenderTexture( + targetSize.x, targetSize.y, renderTargetProperty, + EffekseerRenderTargetDescriptorUtils.CanUseXREyeTextureDescriptor(camera)); // HACK for some smart phone if (depthRenderTexure == null || !depthRenderTexure.Create()) @@ -47,7 +49,9 @@ public static void SetupBackgroundBuffer(ref BackgroundRenderTexture renderTextu #else RenderTextureFormat format = (camera.allowHDR) ? RenderTextureFormat.ARGBHalf : RenderTextureFormat.ARGB32; #endif - renderTexture = new BackgroundRenderTexture(targetSize.x, targetSize.y, 0, format, renderTargetProperty); + renderTexture = new BackgroundRenderTexture( + targetSize.x, targetSize.y, 0, format, renderTargetProperty, + EffekseerRenderTargetDescriptorUtils.CanUseXREyeTextureDescriptor(camera)); // HACK for ZenPhone if (renderTexture == null || !renderTexture.Create()) @@ -287,7 +291,11 @@ public interface IEffekseerRenderer void CleanUp(); - void Render(Camera camera, int additionalMask, RenderTargetProperty renderTargetProperty, CommandBuffer targetCommandBuffer, bool isScriptable, IEffekseerBlitter blitter, bool setDefaultRenderTarget = true); + EffekseerPreparedFrame PrepareFrame(EffekseerRenderFrameInput input); + + void RecordPhase(EffekseerPreparedFrame frame, EffekseerRenderPhase phase, IEffekseerCommandBuffer commandBuffer); + + void EndFrame(EffekseerPreparedFrame frame); void OnPostRender(Camera camera); } @@ -375,7 +383,8 @@ public static Vector2Int GetRequiredSize(Camera camera, RenderTargetProperty ren return new Vector2Int(); } - public BackgroundRenderTexture(int width, int height, int depth, RenderTextureFormat format, RenderTargetProperty renderTargetProperty) + public BackgroundRenderTexture(int width, int height, int depth, RenderTextureFormat format, + RenderTargetProperty renderTargetProperty, bool xrRendering) { if (renderTargetProperty != null) { @@ -390,7 +399,7 @@ public BackgroundRenderTexture(int width, int height, int depth, RenderTextureFo } else { - if (XRSettings.enabled) + if (xrRendering) { renderTexture = new RenderTexture(XRSettings.eyeTextureDesc); } @@ -461,7 +470,7 @@ internal class DepthRenderTexture internal RenderTexture renderTexture; public IntPtr ptr = IntPtr.Zero; - public DepthRenderTexture(int width, int height, RenderTargetProperty renderTargetProperty) + public DepthRenderTexture(int width, int height, RenderTargetProperty renderTargetProperty, bool xrRendering) { if (renderTargetProperty != null) { @@ -469,7 +478,33 @@ public DepthRenderTexture(int width, int height, RenderTargetProperty renderTarg height = renderTargetProperty.colorTargetDescriptor.height; } - RenderTextureDescriptor desc = new RenderTextureDescriptor(width, height, RenderTextureFormat.RHalf); + RenderTextureDescriptor desc; + if (renderTargetProperty != null) + { + // XR-WA-005 (English): Keep the pipeline camera descriptor's dimension, slice count, + // VR usage and dynamic-scale state. A plain 2D temporary texture cannot be sampled + // correctly by Single Pass Instanced or Multiview. Remove this only if Unity starts + // converting 2D effect depth textures to the active XR layout automatically. + // XR-WA-005 (日本語): パイプラインのカメラ Descriptor から dimension、slice 数、 + // VR usage、dynamic-scale 状態を引き継ぎます。通常の 2D 一時テクスチャは Single Pass + // Instanced / Multiview から正しく参照できません。Unity が XR レイアウトへ自動変換する + // ようになった場合のみ削除してください。 + desc = renderTargetProperty.colorTargetDescriptor; + desc.colorFormat = RenderTextureFormat.RHalf; + desc.depthBufferBits = 0; + desc.msaaSamples = 1; + } + else if (xrRendering) + { + desc = XRSettings.eyeTextureDesc; + desc.colorFormat = RenderTextureFormat.RHalf; + desc.depthBufferBits = 0; + desc.msaaSamples = 1; + } + else + { + desc = new RenderTextureDescriptor(width, height, RenderTextureFormat.RHalf); + } renderTexture = new RenderTexture(desc); diff --git a/Dev/Plugin/Assets/Effekseer/Scripts/EffekseerRendererNative.cs b/Dev/Plugin/Assets/Effekseer/Scripts/EffekseerRendererNative.cs index aba2ac26..8632cc34 100644 --- a/Dev/Plugin/Assets/Effekseer/Scripts/EffekseerRendererNative.cs +++ b/Dev/Plugin/Assets/Effekseer/Scripts/EffekseerRendererNative.cs @@ -13,7 +13,7 @@ internal class EffekseerRendererNative : IEffekseerRenderer private class RenderPath : RenderPathBase { - Material fakeMaterial = null; + public Material fakeMaterial = null; public override void Init(Camera camera, CameraEvent cameraEvent, int renderId, bool isCommandBufferFromExternal, bool isScriptable) { @@ -63,11 +63,6 @@ public override void ResetParameters(bool enableDistortion, bool enableDepth, Re RendererUtils.SetupBackgroundBuffer(ref renderTexture, isDistortionEnabled, camera, renderTargetProperty); RendererUtils.SetupDepthBuffer(ref depthTexture, isDepthEnabled, camera, renderTargetProperty); - if (!isCommandBufferFromExternal) - { - SetupEffekseerRenderCommandBuffer(commandBuffer, this.isDistortionEnabled, renderTargetProperty, blitter); - } - // register the command to a camera if (!isCommandBufferFromExternal && !_isScriptable) { @@ -75,117 +70,12 @@ public override void ResetParameters(bool enableDistortion, bool enableDepth, Re } } - private void SetupEffekseerRenderCommandBuffer( - CommandBuffer cmbBuf, - bool enableDistortion, - RenderTargetProperty renderTargetProperty, - IEffekseerBlitter blitter) - { - // add a command to render effects. - if (cmbBuf == null) - { - return; - } - - Action copyBackground = () => - { - if (this.renderTexture != null) - { - // Add a blit command that copy to the distortion texture - // this.commandBuffer.Blit(BuiltinRenderTextureType.CameraTarget, this.renderTexture.renderTexture); - // this.commandBuffer.SetRenderTarget(BuiltinRenderTextureType.CameraTarget); - - if (renderTargetProperty != null) - { - if (renderTargetProperty.colorBufferID.HasValue) - { - blitter.Blit(cmbBuf, renderTargetProperty.colorBufferID.Value, this.renderTexture.renderTexture, renderTargetProperty.xrRendering); - cmbBuf.SetRenderTarget(renderTargetProperty.colorBufferID.Value); - - if (renderTargetProperty.Viewport.HasValue) - { - cmbBuf.SetViewport(renderTargetProperty.Viewport.Value); - } - } - else - { - renderTargetProperty.ApplyToCommandBuffer(cmbBuf, this.renderTexture, blitter); - - if (renderTargetProperty.Viewport.HasValue) - { - cmbBuf.SetViewport(renderTargetProperty.Viewport.Value); - } - } - } - else - { - // TODO : Fix - bool xrRendering = false; - - blitter.Blit(cmbBuf, BuiltinRenderTextureType.CameraTarget, this.renderTexture.renderTexture, xrRendering); - cmbBuf.SetRenderTarget(BuiltinRenderTextureType.CameraTarget); - - // to reset shader settings. SetRenderTarget is not applied until drawing - if (fakeMaterial != null) - { - cmbBuf.DrawProcedural(Matrix4x4.identity, fakeMaterial, 0, MeshTopology.Triangles, 3); - } - } - } - }; - - copyBackground(); - - if (this.depthTexture != null) - { - if (renderTargetProperty != null) - { - renderTargetProperty.ApplyToCommandBuffer(cmbBuf, this.depthTexture, blitter); - - if (renderTargetProperty.Viewport.HasValue) - { - cmbBuf.SetViewport(renderTargetProperty.Viewport.Value); - } - } - else - { - // TODO : Fix - bool xrRendering = false; - - blitter.Blit(cmbBuf, BuiltinRenderTextureType.Depth, this.depthTexture.renderTexture, xrRendering); - cmbBuf.SetRenderTarget(BuiltinRenderTextureType.CameraTarget); - - // to reset shader settings. SetRenderTarget is not applied until drawing - if (fakeMaterial != null) - { - cmbBuf.DrawProcedural(Matrix4x4.identity, fakeMaterial, 0, MeshTopology.Triangles, 3); - } - } - } - - if (renderTargetProperty != null && renderTargetProperty.Viewport.HasValue) - { - cmbBuf.SetViewport(renderTargetProperty.Viewport.Value); - } - - cmbBuf.IssuePluginEvent(Plugin.EffekseerGetRenderBackFunc(), this.renderId); - - copyBackground(); - - if (renderTargetProperty != null && renderTargetProperty.Viewport.HasValue) - { - cmbBuf.SetViewport(renderTargetProperty.Viewport.Value); - } - - cmbBuf.IssuePluginEvent(Plugin.EffekseerGetRenderFrontFunc(), this.renderId); - } - public override void Dispose() { base.Dispose(); } - public void AssignExternalCommandBuffer(CommandBuffer commandBuffer, RenderTargetProperty renderTargetProperty, IEffekseerBlitter blitter) + public void AssignExternalCommandBuffer(CommandBuffer commandBuffer) { if (!isCommandBufferFromExternal) { @@ -193,7 +83,6 @@ public void AssignExternalCommandBuffer(CommandBuffer commandBuffer, RenderTarge } this.commandBuffer = commandBuffer; - SetupEffekseerRenderCommandBuffer(commandBuffer, this.isDistortionEnabled, renderTargetProperty, blitter); } } @@ -226,40 +115,35 @@ public void Render(Camera camera) { if (!EffekseerSettings.Instance.renderAsPostProcessingStack) { - Render(camera, int.MaxValue, null, null, false, standardBlitter); + EffekseerRenderCoordinator.Render(this, new EffekseerRenderFrameInput(camera, int.MaxValue, null, null, false, standardBlitter)); } } - public void Render(Camera camera, int additionalMask, RenderTargetProperty renderTargetProperty, CommandBuffer targetCommandBuffer, bool isScriptable, IEffekseerBlitter blitter, bool setDefaultRenderTarget = true) + public EffekseerPreparedFrame PrepareFrame(EffekseerRenderFrameInput input) { RenderPath path; int allEffectMask; int cameraMask; - renderPathContainer.UpdateRenderPath(disableCullingMask, camera, additionalMask, renderTargetProperty, targetCommandBuffer, isScriptable, blitter, cameraEvent, out path, out allEffectMask, out cameraMask); + renderPathContainer.UpdateRenderPath(disableCullingMask, input.Camera, input.AdditionalMask, + input.RenderTargetProperty, input.TargetCommandBuffer, input.IsScriptable, input.Blitter, + cameraEvent, out path, out allEffectMask, out cameraMask, input.UsesExternalCommands); if (path == null) { - return; + return null; } - // effects shown don't exists - if ((allEffectMask & cameraMask) == 0) + if (path.isCommandBufferFromExternal && input.TargetCommandBuffer != null) { - // Because rendering thread is asynchronous - SpecifyRenderingMatrix(camera, path); - return; + path.AssignExternalCommandBuffer(input.TargetCommandBuffer); } - if (path.isCommandBufferFromExternal) + if (path.commandBuffer != null && !path.isCommandBufferFromExternal) { - path.AssignExternalCommandBuffer(targetCommandBuffer, renderTargetProperty, blitter); + path.commandBuffer.Clear(); } - // if LWRP - if (renderTargetProperty != null) + if (input.RenderTargetProperty != null) { - // flip a rendertaget - // Direct11 : OK (2019, LWRP 5.13) - // Android(OpenGL) : OK (2019, LWRP 5.13) Plugin.EffekseerSetRenderSettings(path.renderId, true); Plugin.EffekseerSetIsBackgroundTextureFlipped(0); } @@ -272,7 +156,6 @@ public void Render(Camera camera, int additionalMask, RenderTargetProperty rende #endif } - // assign a dinsotrion texture if (path.renderTexture != null) { Plugin.EffekseerSetExternalTexture(path.renderId, ExternalTextureType.Background, path.renderTexture.ptr); @@ -291,11 +174,42 @@ public void Render(Camera camera, int additionalMask, RenderTargetProperty rende Plugin.EffekseerSetExternalTexture(path.renderId, ExternalTextureType.Depth, IntPtr.Zero); } - // TODO : specify correct texture formats - var screenSize = BackgroundRenderTexture.GetRequiredSize(camera, renderTargetProperty); + var screenSize = BackgroundRenderTexture.GetRequiredSize(input.Camera, input.RenderTargetProperty); Plugin.EffekseerSetRenderTargetProperty(path.renderId, TextureFormatType.R8G8B8A8_UNORM, TextureFormatType.D32S8, screenSize.x, screenSize.y); - SpecifyRenderingMatrix(camera, path); + SpecifyRenderingMatrix(input.Camera, path); + + return new EffekseerPreparedFrame + { + BackendPath = path, + CommandBuffer = path.commandBuffer, + Background = path.renderTexture, + Depth = path.depthTexture, + TargetCommitMaterial = input.RenderTargetProperty == null && (path.renderTexture != null || path.depthTexture != null) + ? path.fakeMaterial + : null, + IsNativeRenderer = true, + Camera = input.Camera, + HasVisibleEffects = (allEffectMask & cameraMask) != 0, + }; + } + + public void RecordPhase(EffekseerPreparedFrame frame, EffekseerRenderPhase phase, IEffekseerCommandBuffer commandBuffer) + { + var path = frame.BackendPath as RenderPath; + if (path == null || commandBuffer == null) + { + return; + } + + var callback = phase == EffekseerRenderPhase.Back + ? Plugin.EffekseerGetRenderBackFunc() + : Plugin.EffekseerGetRenderFrontFunc(); + commandBuffer.IssuePluginEvent(callback, path.renderId); + } + + public void EndFrame(EffekseerPreparedFrame frame) + { } private static void SpecifyRenderingMatrix(Camera camera, RenderPath path) diff --git a/Dev/Plugin/Assets/Effekseer/Scripts/EffekseerRendererUnity.cs b/Dev/Plugin/Assets/Effekseer/Scripts/EffekseerRendererUnity.cs index 814b5af9..27ed72ae 100644 --- a/Dev/Plugin/Assets/Effekseer/Scripts/EffekseerRendererUnity.cs +++ b/Dev/Plugin/Assets/Effekseer/Scripts/EffekseerRendererUnity.cs @@ -470,17 +470,16 @@ static bool RequiresGlobalBufferFallback() #endif } - static void SetBufferProperty(CommandBuffer commandBuffer, MaterialPropertyBlock prop, string name, ComputeBuffer buffer) + static void SetBufferProperty(IEffekseerCommandBuffer commandBuffer, MaterialPropertyBlock prop, string name, ComputeBuffer buffer) { prop.SetBuffer(name, buffer); - // Workaround: - // On Unity 6 SRP rendering with Vulkan, buffers bound only through + // UNITY-WA-VULKAN-GLOBAL-BUFFER (English): On Unity 6 SRP rendering with Vulkan, buffers bound only through // MaterialPropertyBlock can be treated as unbound for DrawProcedural. - // Mirror the binding to a global shader property as well. - // Keep this isolated here because it is likely compensating for a - // Unity-side issue affecting HDRP/URP paths and may be removable once - // Unity fixes it. + // Mirror the binding globally. Remove this after all supported Unity versions bind it correctly. + // UNITY-WA-VULKAN-GLOBAL-BUFFER (日本語): Unity 6 の Vulkan SRP では MaterialPropertyBlock + // のみに設定した Buffer が DrawProcedural 時に未設定として扱われる場合があります。 + // Global にも同じ Buffer を設定します。対応 Unity 全版で正しく Bind された後に削除してください。 if (RequiresGlobalBufferFallback()) { commandBuffer.SetGlobalBuffer(name, buffer); @@ -917,6 +916,11 @@ public void ResetBuffers() commandBuffer.Clear(); } + ResetRenderingResources(); + } + + public void ResetRenderingResources() + { _materialProps.Reset(); _modelBuffers.Reset(); _customDataBuffers.Reset(); @@ -1014,196 +1018,89 @@ public void Render(Camera camera) { if (!EffekseerSettings.Instance.renderAsPostProcessingStack) { - Render(camera, int.MaxValue, null, null, false, standardBlitter); + EffekseerRenderCoordinator.Render(this, new EffekseerRenderFrameInput(camera, int.MaxValue, null, null, false, standardBlitter)); } } - public void Render(Camera camera, int additionalMask, RenderTargetProperty renderTargetProperty, CommandBuffer targetCommandBuffer, bool isScriptable, IEffekseerBlitter blitter, bool setDefaultRenderTarget = true) + public EffekseerPreparedFrame PrepareFrame(EffekseerRenderFrameInput input) { RenderPath path; int allEffectMask; int cameraMask; - _renderPathContainer.UpdateRenderPath(disableCullingMask, camera, additionalMask, renderTargetProperty, targetCommandBuffer, isScriptable, blitter, cameraEvent, out path, out allEffectMask, out cameraMask); + _renderPathContainer.UpdateRenderPath(disableCullingMask, input.Camera, input.AdditionalMask, + input.RenderTargetProperty, input.TargetCommandBuffer, input.IsScriptable, input.Blitter, + cameraEvent, out path, out allEffectMask, out cameraMask, input.UsesExternalCommands); if (path == null) { - return; - } - - // effects shown don't exists - if ((allEffectMask & cameraMask) == 0) - { - path.ResetBuffers(); - return; - } - - if (path.isCommandBufferFromExternal) - { - path.AssignExternalCommandBuffer(targetCommandBuffer); - } - - // not assigned - if (path.commandBuffer == null) - { - return; - } - - // assign a dinsotrion texture - if (path.renderTexture != null) - { - Plugin.EffekseerSetExternalTexture(path.renderId, ExternalTextureType.Background, path.renderTexture.ptr); - } - else - { - Plugin.EffekseerSetExternalTexture(path.renderId, ExternalTextureType.Background, IntPtr.Zero); + return null; } - if (path.depthTexture != null) - { - Plugin.EffekseerSetExternalTexture(path.renderId, ExternalTextureType.Depth, path.depthTexture.ptr); - } - else + if (path.isCommandBufferFromExternal && input.TargetCommandBuffer != null) { - Plugin.EffekseerSetExternalTexture(path.renderId, ExternalTextureType.Depth, IntPtr.Zero); + path.AssignExternalCommandBuffer(input.TargetCommandBuffer); } - // update view matrixes - Plugin.EffekseerSetProjectionMatrix(path.renderId, Utility.Matrix2Array( - GL.GetGPUProjectionMatrix(camera.projectionMatrix, false))); - Plugin.EffekseerSetCameraMatrix(path.renderId, Utility.Matrix2Array( - camera.worldToCameraMatrix)); - - // Reset command buffer - path.ResetBuffers(); - - // Reset render target - if (renderTargetProperty != null && setDefaultRenderTarget) + if (path.commandBuffer != null && !path.isCommandBufferFromExternal) { - renderTargetProperty.SetDefaultRenderTarget(path.commandBuffer, blitter); + path.commandBuffer.Clear(); } + path.ResetRenderingResources(); - // copy back - if (EffekseerRendererUtils.IsDistortionEnabled) + var frame = new EffekseerPreparedFrame { - if (renderTargetProperty != null) - { - renderTargetProperty.ApplyToCommandBuffer(path.commandBuffer, path.renderTexture, blitter); + BackendPath = path, + CommandBuffer = path.commandBuffer, + Background = path.renderTexture, + Depth = path.depthTexture, + Camera = input.Camera, + HasVisibleEffects = (allEffectMask & cameraMask) != 0, + }; - if (renderTargetProperty.Viewport.HasValue) - { - path.commandBuffer.SetViewport(renderTargetProperty.Viewport.Value); - } - } - else - { - // TODO : Fix - bool xrRendering = false; - - blitter.Blit(path.commandBuffer, BuiltinRenderTextureType.CameraTarget, path.renderTexture.renderTexture, xrRendering); - blitter.SetRenderTarget(path.commandBuffer, BuiltinRenderTextureType.CameraTarget, xrRendering); - } - } - - if (path.depthTexture != null) - { - if (renderTargetProperty != null) - { - renderTargetProperty.ApplyToCommandBuffer(path.commandBuffer, path.depthTexture, blitter); - - if (renderTargetProperty.Viewport.HasValue) - { - path.commandBuffer.SetViewport(renderTargetProperty.Viewport.Value); - } - } - else - { - // TODO : Fix - bool xrRendering = false; - - blitter.Blit(path.commandBuffer, BuiltinRenderTextureType.Depth, path.depthTexture.renderTexture, xrRendering); - blitter.SetRenderTarget(path.commandBuffer, BuiltinRenderTextureType.CameraTarget, xrRendering); - } - } - - // generate render events on this thread - Plugin.EffekseerRenderBack(path.renderId); - - // if memory is lacked, reallocate memory - int maxmumSize = 0; + Plugin.EffekseerSetExternalTexture(path.renderId, ExternalTextureType.Background, path.renderTexture != null ? path.renderTexture.ptr : IntPtr.Zero); + Plugin.EffekseerSetExternalTexture(path.renderId, ExternalTextureType.Depth, path.depthTexture != null ? path.depthTexture.ptr : IntPtr.Zero); + Plugin.EffekseerSetProjectionMatrix(path.renderId, Utility.Matrix2Array(GL.GetGPUProjectionMatrix(input.Camera.projectionMatrix, false))); + Plugin.EffekseerSetCameraMatrix(path.renderId, Utility.Matrix2Array(input.Camera.worldToCameraMatrix)); + return frame; + } - for (int i = 0; i < Plugin.GetUnityStrideBufferCount(); i++) + public void RecordPhase(EffekseerPreparedFrame frame, EffekseerRenderPhase phase, IEffekseerCommandBuffer commandBuffer) + { + var path = frame.BackendPath as RenderPath; + if (path == null || commandBuffer == null) { - var buf = Plugin.GetUnityStrideBufferParameter(i); - maxmumSize = Math.Max(maxmumSize, buf.Size); + return; } - while (Plugin.GetUnityRenderParameterCount() > 0 && maxmumSize > path._computeBufferBack.GetCPUData().Length) + if (phase == EffekseerRenderPhase.Back) { - path.ReallocateComputeBuffer(maxmumSize); + Plugin.EffekseerRenderBack(path.renderId); } - - if (renderTargetProperty != null && renderTargetProperty.Viewport.HasValue) + else { - path.commandBuffer.SetViewport(renderTargetProperty.Viewport.Value); + Plugin.EffekseerRenderFront(path.renderId); } + EnsureComputeBufferCapacity(path); + var buffers = phase == EffekseerRenderPhase.Back ? path._computeBufferBack : path._computeBufferFront; + RenderInternal(commandBuffer, buffers, path._materialProps, path._modelBuffers, path._customDataBuffers, frame.Background, frame.Depth); + } - RenderInternal(path.commandBuffer, path._computeBufferBack, path._materialProps, path._modelBuffers, path._customDataBuffers, path.renderTexture, path.depthTexture); - - // Distortion - if (EffekseerRendererUtils.IsDistortionEnabled && - (path.renderTexture != null || renderTargetProperty != null)) - { - // Add a blit command that copy to the distortion texture - if (renderTargetProperty != null && renderTargetProperty.colorBufferID.HasValue) - { - blitter.Blit(path.commandBuffer, renderTargetProperty.colorBufferID.Value, path.renderTexture.renderTexture, renderTargetProperty.xrRendering); - blitter.SetRenderTarget(path.commandBuffer, renderTargetProperty.colorBufferID.Value, renderTargetProperty.xrRendering); - - if (renderTargetProperty.Viewport.HasValue) - { - path.commandBuffer.SetViewport(renderTargetProperty.Viewport.Value); - } - } - else if (renderTargetProperty != null) - { - renderTargetProperty.ApplyToCommandBuffer(path.commandBuffer, path.renderTexture, blitter); - - if (renderTargetProperty.Viewport.HasValue) - { - path.commandBuffer.SetViewport(renderTargetProperty.Viewport.Value); - } - } - else - { - // TODO : Fix - bool xrRendering = false; - - blitter.Blit(path.commandBuffer, BuiltinRenderTextureType.CameraTarget, path.renderTexture.renderTexture, xrRendering); - blitter.SetRenderTarget(path.commandBuffer, BuiltinRenderTextureType.CameraTarget, xrRendering); - } - } - - Plugin.EffekseerRenderFront(path.renderId); - - maxmumSize = 0; + public void EndFrame(EffekseerPreparedFrame frame) + { + } + void EnsureComputeBufferCapacity(RenderPath path) + { + int maximumSize = 0; for (int i = 0; i < Plugin.GetUnityStrideBufferCount(); i++) { - var buf = Plugin.GetUnityStrideBufferParameter(i); - maxmumSize = Math.Max(maxmumSize, buf.Size); + var buffer = Plugin.GetUnityStrideBufferParameter(i); + maximumSize = Math.Max(maximumSize, buffer.Size); } - // if memory is lacked, reallocate memory - while (Plugin.GetUnityRenderParameterCount() > 0 && maxmumSize > path._computeBufferFront.GetCPUData().Length) + while (Plugin.GetUnityRenderParameterCount() > 0 && maximumSize > path._computeBufferBack.GetCPUData().Length) { - path.ReallocateComputeBuffer(maxmumSize); + path.ReallocateComputeBuffer(maximumSize); } - - if (renderTargetProperty != null && renderTargetProperty.Viewport.HasValue) - { - path.commandBuffer.SetViewport(renderTargetProperty.Viewport.Value); - } - - RenderInternal(path.commandBuffer, path._computeBufferFront, path._materialProps, path._modelBuffers, path._customDataBuffers, path.renderTexture, path.depthTexture); } Texture GetCachedTexture(IntPtr key, BackgroundRenderTexture background, DepthRenderTexture depth, DummyTextureType type) @@ -1220,7 +1117,7 @@ Texture GetDepthTexture(DepthRenderTexture depth) return EffekseerSystem.GetCachedTexture(IntPtr.Zero, DummyTextureType.White); } - unsafe void RenderInternal(CommandBuffer commandBuffer, ComputeBufferCollection computeBuffer, MaterialPropCollection matPropCol, ModelBufferCollection modelBufferCol, CustomDataBufferCollection customDataBufferCol, BackgroundRenderTexture background, DepthRenderTexture depth) + unsafe void RenderInternal(IEffekseerCommandBuffer commandBuffer, ComputeBufferCollection computeBuffer, MaterialPropCollection matPropCol, ModelBufferCollection modelBufferCol, CustomDataBufferCollection customDataBufferCol, BackgroundRenderTexture background, DepthRenderTexture depth) { var renderParameterCount = Plugin.GetUnityRenderParameterCount(); // var vertexBufferSize = Plugin.GetUnityRenderVertexBufferCount(); @@ -1259,7 +1156,7 @@ unsafe void RenderInternal(CommandBuffer commandBuffer, ComputeBufferCollection } } - unsafe void RenderSprite(Plugin.UnityRenderParameter parameter, IntPtr infoBuffer, CommandBuffer commandBuffer, ComputeBufferCollection computeBuffer, MaterialPropCollection matPropCol, BackgroundRenderTexture background, DepthRenderTexture depth) + unsafe void RenderSprite(Plugin.UnityRenderParameter parameter, IntPtr infoBuffer, IEffekseerCommandBuffer commandBuffer, ComputeBufferCollection computeBuffer, MaterialPropCollection matPropCol, BackgroundRenderTexture background, DepthRenderTexture depth) { var prop = matPropCol.GetNext(); @@ -1425,7 +1322,7 @@ private static unsafe void AssignUniforms(Plugin.UnityRenderParameter parameter, } } - unsafe void RenderModdel(Plugin.UnityRenderParameter parameter, IntPtr infoBuffer, CommandBuffer commandBuffer, MaterialPropCollection matPropCol, ModelBufferCollection modelBufferCol1, CustomDataBufferCollection customDataBuffers, BackgroundRenderTexture background, DepthRenderTexture depth) + unsafe void RenderModdel(Plugin.UnityRenderParameter parameter, IntPtr infoBuffer, IEffekseerCommandBuffer commandBuffer, MaterialPropCollection matPropCol, ModelBufferCollection modelBufferCol1, CustomDataBufferCollection customDataBuffers, BackgroundRenderTexture background, DepthRenderTexture depth) { // Draw model var modelParameters1 = ((Plugin.UnityRenderModelParameter1*)(((byte*)infoBuffer.ToPointer()) + parameter.VertexBufferOffset)); diff --git a/Dev/Plugin/Assets/Effekseer/Scripts/EffekseerSystem.cs b/Dev/Plugin/Assets/Effekseer/Scripts/EffekseerSystem.cs index 63ef9f71..aeca37b1 100644 --- a/Dev/Plugin/Assets/Effekseer/Scripts/EffekseerSystem.cs +++ b/Dev/Plugin/Assets/Effekseer/Scripts/EffekseerSystem.cs @@ -190,8 +190,7 @@ public bool CanUseURPRasterPass { get { - return RendererType == EffekseerRendererType.Unity && - !EffekseerRendererUtils.IsDistortionEnabled && + return !EffekseerRendererUtils.IsDistortionEnabled && !EffekseerRendererUtils.IsDepthEnabled; } } diff --git a/Dev/Plugin/Assets/Effekseer/Scripts/Rendering.meta b/Dev/Plugin/Assets/Effekseer/Scripts/Rendering.meta new file mode 100644 index 00000000..8fb76321 --- /dev/null +++ b/Dev/Plugin/Assets/Effekseer/Scripts/Rendering.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 2a4e9fd139a84b34851ec5b9c3e82470 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Dev/Plugin/Assets/Effekseer/Scripts/Rendering/EffekseerCommandBuffer.cs b/Dev/Plugin/Assets/Effekseer/Scripts/Rendering/EffekseerCommandBuffer.cs new file mode 100644 index 00000000..91082a13 --- /dev/null +++ b/Dev/Plugin/Assets/Effekseer/Scripts/Rendering/EffekseerCommandBuffer.cs @@ -0,0 +1,36 @@ +using System; +using UnityEngine; +using UnityEngine.Rendering; + +namespace Effekseer.Internal +{ + internal sealed class EffekseerCommandBuffer : IEffekseerCommandBuffer + { + readonly CommandBuffer _commandBuffer; + + public EffekseerCommandBuffer(CommandBuffer commandBuffer) + { + _commandBuffer = commandBuffer; + } + + public void SetViewport(Rect viewport) + { + _commandBuffer?.SetViewport(viewport); + } + + public void SetGlobalBuffer(string name, ComputeBuffer buffer) + { + _commandBuffer?.SetGlobalBuffer(name, buffer); + } + + public void DrawProcedural(Matrix4x4 matrix, Material material, int shaderPass, MeshTopology topology, int vertexCount, int instanceCount, MaterialPropertyBlock properties) + { + _commandBuffer?.DrawProcedural(matrix, material, shaderPass, topology, vertexCount, instanceCount, properties); + } + + public void IssuePluginEvent(IntPtr callback, int eventId) + { + _commandBuffer?.IssuePluginEvent(callback, eventId); + } + } +} diff --git a/Dev/Plugin/Assets/Effekseer/Scripts/Rendering/EffekseerCommandBuffer.cs.meta b/Dev/Plugin/Assets/Effekseer/Scripts/Rendering/EffekseerCommandBuffer.cs.meta new file mode 100644 index 00000000..5256d66d --- /dev/null +++ b/Dev/Plugin/Assets/Effekseer/Scripts/Rendering/EffekseerCommandBuffer.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 20c0fc63f41f4530bd37575b7474d247 diff --git a/Dev/Plugin/Assets/Effekseer/Scripts/Rendering/EffekseerPreparedFrame.cs b/Dev/Plugin/Assets/Effekseer/Scripts/Rendering/EffekseerPreparedFrame.cs new file mode 100644 index 00000000..c5c1e084 --- /dev/null +++ b/Dev/Plugin/Assets/Effekseer/Scripts/Rendering/EffekseerPreparedFrame.cs @@ -0,0 +1,18 @@ +using UnityEngine; +using UnityEngine.Rendering; + +namespace Effekseer.Internal +{ + public sealed class EffekseerPreparedFrame + { + internal object BackendPath { get; set; } + internal CommandBuffer CommandBuffer { get; set; } + internal BackgroundRenderTexture Background { get; set; } + internal DepthRenderTexture Depth { get; set; } + internal Material TargetCommitMaterial { get; set; } + internal bool IsNativeRenderer { get; set; } + + public Camera Camera { get; internal set; } + public bool HasVisibleEffects { get; internal set; } + } +} diff --git a/Dev/Plugin/Assets/Effekseer/Scripts/Rendering/EffekseerPreparedFrame.cs.meta b/Dev/Plugin/Assets/Effekseer/Scripts/Rendering/EffekseerPreparedFrame.cs.meta new file mode 100644 index 00000000..2e13e61a --- /dev/null +++ b/Dev/Plugin/Assets/Effekseer/Scripts/Rendering/EffekseerPreparedFrame.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 324698824b5a44d985992835839670c1 diff --git a/Dev/Plugin/Assets/Effekseer/Scripts/Rendering/EffekseerRenderCoordinator.cs b/Dev/Plugin/Assets/Effekseer/Scripts/Rendering/EffekseerRenderCoordinator.cs new file mode 100644 index 00000000..949ff979 --- /dev/null +++ b/Dev/Plugin/Assets/Effekseer/Scripts/Rendering/EffekseerRenderCoordinator.cs @@ -0,0 +1,101 @@ +using UnityEngine; +using UnityEngine.Rendering; + +namespace Effekseer.Internal +{ + public static class EffekseerRenderCoordinator + { + public static void Render(IEffekseerRenderer renderer, EffekseerRenderFrameInput input) + { + var frame = renderer.PrepareFrame(input); + if (frame == null || !frame.HasVisibleEffects || frame.CommandBuffer == null) + { + return; + } + + var commandBuffer = new EffekseerCommandBuffer(frame.CommandBuffer); + PreparePhaseTarget(input, frame, true); + CommitNativeTargetIfRequired(frame, commandBuffer); + renderer.RecordPhase(frame, EffekseerRenderPhase.Back, commandBuffer); + + PreparePhaseTarget(input, frame, false); + CommitNativeTargetIfRequired(frame, commandBuffer); + renderer.RecordPhase(frame, EffekseerRenderPhase.Front, commandBuffer); + renderer.EndFrame(frame); + } + + public static void RenderExternal(IEffekseerRenderer renderer, EffekseerRenderFrameInput input, IEffekseerCommandBuffer commandBuffer) + { + var frame = renderer.PrepareFrame(input); + if (frame == null || !frame.HasVisibleEffects) + { + return; + } + + renderer.RecordPhase(frame, EffekseerRenderPhase.Back, commandBuffer); + renderer.RecordPhase(frame, EffekseerRenderPhase.Front, commandBuffer); + renderer.EndFrame(frame); + } + + static void PreparePhaseTarget(EffekseerRenderFrameInput input, EffekseerPreparedFrame frame, bool includeDepth) + { + var commandBuffer = frame.CommandBuffer; + var target = input.RenderTargetProperty; + var blitter = input.Blitter; + + if (target != null && input.SetDefaultRenderTarget) + { + target.SetDefaultRenderTarget(commandBuffer, blitter); + } + + if (frame.Background != null) + { + if (target != null) + { + target.ApplyToCommandBuffer(commandBuffer, frame.Background, blitter); + } + else + { + blitter.Blit(commandBuffer, BuiltinRenderTextureType.CameraTarget, frame.Background.renderTexture, false); + blitter.SetRenderTarget(commandBuffer, BuiltinRenderTextureType.CameraTarget, false); + } + } + + if (includeDepth && frame.Depth != null) + { + if (target != null) + { + target.ApplyToCommandBuffer(commandBuffer, frame.Depth, blitter); + } + else + { + blitter.Blit(commandBuffer, BuiltinRenderTextureType.Depth, frame.Depth.renderTexture, false); + blitter.SetRenderTarget(commandBuffer, BuiltinRenderTextureType.CameraTarget, false); + } + } + + if (target != null && target.Viewport.HasValue) + { + commandBuffer.SetViewport(target.Viewport.Value); + } + } + + static void CommitNativeTargetIfRequired(EffekseerPreparedFrame frame, IEffekseerCommandBuffer commandBuffer) + { + if (!frame.IsNativeRenderer || frame.TargetCommitMaterial == null) + { + return; + } + + // XR-WA-NATIVE-TARGET-COMMIT (English): On the affected Editor/PS4 native-renderer path, + // SetRenderTarget is not committed before the plugin event unless a draw is recorded. + // This zero-impact fake draw commits the intended target. Remove it only after every + // supported graphics API applies the target before IssuePluginEvent without this draw. + // XR-WA-NATIVE-TARGET-COMMIT (日本語): 対象となる Editor/PS4 の Native Renderer 経路では、 + // 描画を記録しないと SetRenderTarget がプラグインイベント前に確定しません。 + // この表示に影響しない Fake Draw で目的のターゲットを確定します。対応対象の全 Graphics API で + // Fake Draw なしに IssuePluginEvent 前へ反映されることを確認できた場合のみ削除してください。 + commandBuffer.DrawProcedural(Matrix4x4.identity, frame.TargetCommitMaterial, 0, MeshTopology.Triangles, 3, 1, null); + } + } +} diff --git a/Dev/Plugin/Assets/Effekseer/Scripts/Rendering/EffekseerRenderCoordinator.cs.meta b/Dev/Plugin/Assets/Effekseer/Scripts/Rendering/EffekseerRenderCoordinator.cs.meta new file mode 100644 index 00000000..53bf7e6f --- /dev/null +++ b/Dev/Plugin/Assets/Effekseer/Scripts/Rendering/EffekseerRenderCoordinator.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: e15f233a2b7346ed92c98c0c93b6499e diff --git a/Dev/Plugin/Assets/Effekseer/Scripts/Rendering/EffekseerRenderFrameInput.cs b/Dev/Plugin/Assets/Effekseer/Scripts/Rendering/EffekseerRenderFrameInput.cs new file mode 100644 index 00000000..e97dbbb5 --- /dev/null +++ b/Dev/Plugin/Assets/Effekseer/Scripts/Rendering/EffekseerRenderFrameInput.cs @@ -0,0 +1,31 @@ +using UnityEngine; +using UnityEngine.Rendering; + +namespace Effekseer.Internal +{ + public sealed class EffekseerRenderFrameInput + { + public Camera Camera { get; } + public int AdditionalMask { get; } + public RenderTargetProperty RenderTargetProperty { get; } + public CommandBuffer TargetCommandBuffer { get; } + public bool IsScriptable { get; } + public IEffekseerBlitter Blitter { get; } + public bool SetDefaultRenderTarget { get; } + public bool UsesExternalCommands { get; } + + public EffekseerRenderFrameInput(Camera camera, int additionalMask, RenderTargetProperty renderTargetProperty, + CommandBuffer targetCommandBuffer, bool isScriptable, IEffekseerBlitter blitter, + bool setDefaultRenderTarget = true, bool usesExternalCommands = false) + { + Camera = camera; + AdditionalMask = additionalMask; + RenderTargetProperty = renderTargetProperty; + TargetCommandBuffer = targetCommandBuffer; + IsScriptable = isScriptable; + Blitter = blitter; + SetDefaultRenderTarget = setDefaultRenderTarget; + UsesExternalCommands = usesExternalCommands; + } + } +} diff --git a/Dev/Plugin/Assets/Effekseer/Scripts/Rendering/EffekseerRenderFrameInput.cs.meta b/Dev/Plugin/Assets/Effekseer/Scripts/Rendering/EffekseerRenderFrameInput.cs.meta new file mode 100644 index 00000000..f4b6c9ef --- /dev/null +++ b/Dev/Plugin/Assets/Effekseer/Scripts/Rendering/EffekseerRenderFrameInput.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 6d04bfab718a4894a112714fb854e96f diff --git a/Dev/Plugin/Assets/Effekseer/Scripts/Rendering/EffekseerRenderPhase.cs b/Dev/Plugin/Assets/Effekseer/Scripts/Rendering/EffekseerRenderPhase.cs new file mode 100644 index 00000000..71b266e9 --- /dev/null +++ b/Dev/Plugin/Assets/Effekseer/Scripts/Rendering/EffekseerRenderPhase.cs @@ -0,0 +1,8 @@ +namespace Effekseer.Internal +{ + public enum EffekseerRenderPhase + { + Back, + Front, + } +} diff --git a/Dev/Plugin/Assets/Effekseer/Scripts/Rendering/EffekseerRenderPhase.cs.meta b/Dev/Plugin/Assets/Effekseer/Scripts/Rendering/EffekseerRenderPhase.cs.meta new file mode 100644 index 00000000..95f0e781 --- /dev/null +++ b/Dev/Plugin/Assets/Effekseer/Scripts/Rendering/EffekseerRenderPhase.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: a922edb0e2684dacba35bc242ed403db diff --git a/Dev/Plugin/Assets/Effekseer/Scripts/Rendering/EffekseerRenderTargetDescriptorUtils.cs b/Dev/Plugin/Assets/Effekseer/Scripts/Rendering/EffekseerRenderTargetDescriptorUtils.cs new file mode 100644 index 00000000..0b79e612 --- /dev/null +++ b/Dev/Plugin/Assets/Effekseer/Scripts/Rendering/EffekseerRenderTargetDescriptorUtils.cs @@ -0,0 +1,69 @@ +using UnityEngine; +using UnityEngine.Rendering; +using UnityEngine.XR; + +namespace Effekseer.Internal +{ + public static class EffekseerRenderTargetDescriptorUtils + { + public static bool IsStereoRendering(Camera camera) + { + return camera != null && camera.stereoEnabled; + } + + public static bool CanUseXREyeTextureDescriptor(Camera camera) + { + // XR-WA-005 (English): XRSettings.enabled is application-wide and can be true for a + // non-stereo camera. Use eyeTextureDesc only when the current camera is rendering stereo. + // Remove this condition when Unity exposes a camera-specific Built-in XR descriptor. + // XR-WA-005 (日本語): XRSettings.enabled はアプリ全体の状態であり、非Stereo Cameraでも + // trueになり得ます。現在のCameraがStereo描画する場合のみeyeTextureDescを使用します。 + // Built-in向けのカメラ単位XR Descriptorが提供された場合のみ削除してください。 + return IsStereoRendering(camera) && XRSettings.enabled; + } + + public static RenderTextureDescriptor CreateTemporaryColorDescriptor( + RenderTexture source, Camera camera) + { + var sourceDescriptor = source.descriptor; + var descriptor = new RenderTextureDescriptor( + source.width, source.height, source.format, 0, source.mipmapCount); + descriptor.useDynamicScale = sourceDescriptor.useDynamicScale; + + if (IsStereoRendering(camera)) + { + // XR-WA-005 (English): Inherit only the XR layout from the source. Copying HDRP's full + // camera descriptor also imports attachment-specific flags and packed GraphicsFormat + // details that are not part of Effekseer's temporary distortion texture contract. + // Keep source.format as Unity's logical channel layout. Remove this filtering when HDRP + // exposes a descriptor intended for temporary sampled color textures. + // XR-WA-005 (日本語): SourceからXR Layoutだけを継承します。HDRPのCamera Descriptor全体を + // コピーすると、Effekseerの一時Distortion Textureには不要なAttachment固有Flagや + // Packed GraphicsFormatの詳細まで引き継がれます。Unityの論理Channel Layoutである + // source.formatを使用します。HDRPがSample用一時Color Texture向けDescriptorを + // 提供した場合のみ、このFilteringを削除してください。 + descriptor.dimension = sourceDescriptor.dimension; + descriptor.volumeDepth = sourceDescriptor.volumeDepth; + descriptor.vrUsage = sourceDescriptor.vrUsage; + } + + return descriptor; + } + + public static RenderTextureDescriptor CreatePostProcessingDescriptor( + Camera camera, int width, int height, RenderTextureFormat format) + { + if (CanUseXREyeTextureDescriptor(camera)) + { + // XR-WA-005 (English): PostProcessing does not expose its source descriptor, so inherit + // eyeTextureDesc for an XR camera. Remove this when the source descriptor becomes public. + // XR-WA-005 (日本語): PostProcessingはSource Descriptorを公開しないため、XR Cameraでは + // eyeTextureDescを継承します。Source Descriptorが公開された場合のみ削除してください。 + return XRSettings.eyeTextureDesc; + } + + return new RenderTextureDescriptor(width, height, format); + } + + } +} diff --git a/Dev/Plugin/Assets/Effekseer/Scripts/Rendering/EffekseerRenderTargetDescriptorUtils.cs.meta b/Dev/Plugin/Assets/Effekseer/Scripts/Rendering/EffekseerRenderTargetDescriptorUtils.cs.meta new file mode 100644 index 00000000..65c27d4b --- /dev/null +++ b/Dev/Plugin/Assets/Effekseer/Scripts/Rendering/EffekseerRenderTargetDescriptorUtils.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: e43af99eb595435095d79c928f505b50 diff --git a/Dev/Plugin/Assets/Effekseer/Scripts/Rendering/IEffekseerCommandBuffer.cs b/Dev/Plugin/Assets/Effekseer/Scripts/Rendering/IEffekseerCommandBuffer.cs new file mode 100644 index 00000000..98a7eca8 --- /dev/null +++ b/Dev/Plugin/Assets/Effekseer/Scripts/Rendering/IEffekseerCommandBuffer.cs @@ -0,0 +1,13 @@ +using System; +using UnityEngine; + +namespace Effekseer.Internal +{ + public interface IEffekseerCommandBuffer + { + void SetViewport(Rect viewport); + void SetGlobalBuffer(string name, ComputeBuffer buffer); + void DrawProcedural(Matrix4x4 matrix, Material material, int shaderPass, MeshTopology topology, int vertexCount, int instanceCount, MaterialPropertyBlock properties); + void IssuePluginEvent(IntPtr callback, int eventId); + } +} diff --git a/Dev/Plugin/Assets/Effekseer/Scripts/Rendering/IEffekseerCommandBuffer.cs.meta b/Dev/Plugin/Assets/Effekseer/Scripts/Rendering/IEffekseerCommandBuffer.cs.meta new file mode 100644 index 00000000..7efce6f7 --- /dev/null +++ b/Dev/Plugin/Assets/Effekseer/Scripts/Rendering/IEffekseerCommandBuffer.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 5d40db24d17e4198b99011932b279ec8