Hi Spine team and community,
I'm working on a Unity URP project where I need to render Spine characters to a custom mask texture (R8 format) for motion blur exclusion. I'm using CommandBuffer.DrawRenderer to draw Spine MeshRenderers with a custom shader that should alpha-clip based on the texture's alpha channel.
Setup:
Unity 2022.3+ with URP
Spine Unity Runtime 4.1
Custom render pass that uses CommandBuffer.DrawRenderer(renderer, customMaterial, submeshIndex, 0)
Custom shader samples _MainTex and clips pixels based on texture.a * vertex.a
The Problem: When I render Spine characters with this approach, the alpha clipping doesn't work correctly - I get rectangular/boxy masks instead of character-shaped masks. Regular Unity SpriteRenderers work perfectly with the same shader and approach.
What Works:
✅ SpriteRenderers render correctly with proper alpha cutoff
✅ Minecart (Spine object) renders correctly when alone
✅ Clone character (Spine object) renders correctly when alone
What Doesn't Work:
❌ When both Spine objects are in scene, alpha clipping fails on the character
❌ Multiple texture pages seem to cause issues even with per-texture materials
❌ The UVs appear correct in debug mode (showing proper gradient colors)
❌ Texture sampling seems to return wrong alpha values
Current Implementation:
// Create unique material per texture
Material texMaterial = new Material(maskMaterial);
texMaterial.SetTexture("_MainTex", spineAtlasTexture);
texMaterial.SetFloat("_AlphaThreshold", 0.1f);
// Draw each submesh individually with immediate execution
CommandBuffer cmd = CommandBufferPool.Get("MaskDraw");
cmd.SetRenderTarget(maskTexture, RenderBufferLoadAction.Load, RenderBufferStoreAction.Store);
cmd.DrawRenderer(meshRenderer, texMaterial, submeshIndex, 0);
context.ExecuteCommandBuffer(cmd);
Shader Fragment (simplified):
half4 texColor = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, input.uv);
half combinedAlpha = texColor.a * input.color.a; // vertex alpha from Spine
clip(combinedAlpha - _AlphaThreshold);
return half4(1, 1, 1, 1); // White mask
Questions:
Does Spine use premultiplied alpha in its texture atlases that might affect alpha sampling?
Are there special considerations when using CommandBuffer.DrawRenderer with Spine meshes vs regular sprites?
Should I be accessing the mesh data differently or using a specific material property?
Is there a Spine-specific way to render to custom render targets that handles alpha correctly?
What I've Tried:
✅ Lowering alpha threshold from 0.5 to 0.1
✅ Disabling GPU instancing and batching (DisableBatching = "True")
✅ Creating separate material instances per texture
✅ Individual command buffers per submesh with immediate execution
✅ Verified UVs are correct using debug visualization
❌ Issue persists despite all attempts
The fact that it works perfectly when there's only ONE Spine object suggests it's related to how multiple Spine textures/materials interact with CommandBuffer.DrawRenderer, but I can't figure out why the texture alpha isn't being sampled correctly.
Any insights into how Spine's material/texture system works that might explain this behavior? Is there a recommended approach for rendering Spine objects to custom render targets?
Thanks in advance for any help!