Render texture, HDR and transparent background

Hi,

I’m rendering a character into a render texture and display that as part of a character sheet. So I need to have the camera which draws the render texture to have a transparent background, which I achieve by choosing a solid color with an alpha of 0. This works fine, as long as the camera rendering the render texture has HDR disabled.

The caveat of this is, that no HDR colors are rendered to this texture. They just appear white. As soon as I toggle the HDR flag on the camera, the colors are drawn correctly, but the background is no longer transparent. I tried changing the color and depth stencil format of the render texture, but to no avail.

I’m using the Built-In Renderer in Unity 2021.3.6f.

Maybe some pictures are in order to clarify. I’m talking about the purple particle effect. This is what it looks like in scene view:

This is how my render texture looks with HDR disabled / enabled in game view:

As you can see, if I switch the camera to HDR, the colors of the effect are shown correctly, but the transparency is gone and the opaque color is rendered instead.

This is only a problem with the render texture, in the 3d world the character and effect look just fine and as they’re supposed to.

Any thoughts on a solution would be appreciated. :slight_smile:

I’m baffled. 62 views and no reply.

Is this question stupid and nobody bothers to answer or is there no solution?

It’s not stupid, but it’s difficult to answer.

I can’t tell you exactly what the problem is, but here are some thoughts:

  • HDR means you have to use a floating point render texture. What is your render texture format?
  • I’m not sure if your conclusion is correct that translucency doesn’t work. If the smoke was no longer translucent, you wouldn’t see the torch at all, would you?
  • What are you trying to achieve? HDR can be used in two ways - with and without tonemapping. The latter requires a HDR monitor.
  • Not every GPU/driver supports alpha blending with floating point render targets

Some random thoughts:

You want the camera to use a solid background of black with an alpha of zero. If it’s any color but black you’re going to have a hard time. This is for reasons I’ll get to later.

Any transparent shader you use will need to be modified to properly write its alpha value out. I guarantee you it’s currently wrong for this use case, as most shaders aren’t written with using the resulting rendered alpha channel in mind, only for making sure the output alpha value blends the RGB color values how you want. For example if you’re using traditional alpha blending, like Blend SrcAlpha OneMinusSrcAlpha this will be writing the alpha multiplied by itself to the alpha of the render target rather than the actual alpha. You will want Blend SrcAlpha OneMinusSrcAlpha, One OneMinusSrcAlpha.

When displaying the render texture you need to use a premultiplied alpha shader. None of the shaders that come with Unity are properly setup for this. Even the ones that claim to be premultiplied alpha shaders. They’re all broken or otherwise modified in ways to not be useful. But the short version is you need a shader that samples the render texture and outputs the RGBA as is, and uses Blend One OneMinusSrcAlpha. Other shaders will cause the transparent areas to look dark or otherwise weird, which could be part of what’s happening here.

All of the above is because whenever you render a transparent shader to a render texture, by definition the resulting image is premultiplied by the alpha. This is much different that your usual transparent FBX source textures which are probably mostly white or other colors in the partially or fully transparent areas, but are dark or black once rendered because it’s being multiplied by the alpha before being added to the render target. That first SrcAlpha in the Blend is saying “multiply the src color by the src alpha”.

The last thing would be is your project using Gamma or Linear color space in the project settings? That setting can cause some changes in how you have to handle rendering in the UI, or in other situations. Also to echo @c0d3_m0nk3y , what format is the render texture? How are you setting it to HDR?

1 Like

Hi,

first off, thanks for your replies.

I’m using Linear Color Space and a R32G32B32A32_SFLOAT render texture. When I wrote this, I quickly clicked through all available color formats, but colorwise they look all the same (no HDR color applied). Also it doesn’t make any difference for the background transparency issue, if HDR is turned on for the render texture camera. Here are the complete settings for the texture:

I’m not sure about all settings, but as I mentioned, no matter what I select or which boxes I tick, it doesn’t make any difference for the issue I described.

As c0d3_m0nk3y pointed out, it’s not a general problem with transparency, as the particle effects shown have transparency applied. It’s the background for the render texture that is no longer is transparent, as soon as I turn on HDR for the responsible camera.

I made the solid color of the camera green (alpha 0) and increased the particles size to better visualize the effect. I use a solid black color with alpha 0 otherwise. I don’t have an HDR monitor.

To clarify what I want to achieve: I want a character to be rendered by a dedicated camera to a render texture, so I can add it as a Raw Image component into Unity UI. The character should have it’s equipped weapon in his/her hand. These weapons can have different particle effects, depending on the type of damage and/or status effects they can apply. The pictures shown are from a magic staff that deals magic damage, so there should be some sparkly particles flying around. For a poisonous weapon there should be some green stuff floating from the weapon etc. You get the picture.

The screenshots were taken with a particle effect out of this FX package and utilises a custom shader for the particles, which came with the package. This shader uses a HDR color, and that’s how I stumbled upon this problem. I guess I’ll have to dig into that shader and see what I can come up with.

Nevertheless, I encountered the problem (I think) that bgolus describes. When adding a standard particle effect the particles are only drawn when they’re on top of an opaque surface in the render texture. I took the PoisonGas from the Unity Particle Pack. It uses the Particles/Standard Unlit shader.

From left to right: Scene View / Render Texture as shown in the Inspector / Raw Image in Unity UI / Material with Unity Standard Shader (Rendering Mode Transparent) applied to a plane in 3D world

When I switch the particle shader to Mobile/Particles/Alpha Blended it shows as I would’ve it expected to (like the original render texture in the inspector view), so this might be suitable workaround, but I haven’t checked it out in detail.

Please note that this is a different but somehow related problem, to the one I described in my previous post. But both of them need fixing. If I understood bgolus correctly, I can solve this one here by editing the shader and manually set the alpha blend mode to the correct value. I will try this eventually.

I just reread my postings and I thought maybe i didn’t describe the problems I’m experiencing in an understandable fashion. So I’ll try to wrap it up again, with emphasis on simplicity and give a step by step guide, so you can set it up by yourself and see what I mean.

Also I have a new insight, that this is somehow connected to post processing (I’m using the latest post processing stack 3.2.2). At least I didn’t experience this with no post processing layer attached to the RTT camera.

If HDR is activated on a camera with a post processing layer that renders into a texture, the alpha value of the background color isn’t respected anymore.

Steps to set it up:

  • Install Post Processing 3.2.2 via Package Manager.

  • Create an empty scene.

  • Add a new layer ‘post process’.

  • Create a new render texture.

  • Create a new camera (I’ll call it RTT camera). Assign the newly created render texture to Target Texture. Set HDR to off. Remove Audio Listener component.

  • Set RTT camera clear flags to ‘Solid Color’ and background to any color with alpha 0 (bright green in my example).

  • Create a new GameObject and attach a new Post-process Volume component.

  • Hit ‘New’ on that volume to create a new empty profile and automatically assign it.

  • Set Layer of Post-process volume GameObject to ‘post process’.

  • Attach a Post-process Layer to both Main Camera and RTT Camera.

  • Set Volume blending/Layer to ‘post process’ on both newly created Post-process layers.

  • Create a canvas with an opaque fullscreen image.

  • Create a raw image and assign the newly created render texture to the Texture field.

  • In Game View you should see just the fullscreen image, but no render texture, because the RTT cameras background color has an alpha of 0.

  • Activate HDR on the RTT camera. The raw image is now visible with the background color selected in the RTT camera, no matter the alpha value of that color.

  • Remove or deactivate the Post-process Layer of RTT camera. The raw image is not visible again.

The effect is even better to observe with a cube (set on a separate layer) in scene and the RTT camera Culling Mask to render only the layer of the cube. But as it produces extra steps and is not needed to get this effect, I left it out of the guide.

Game View / RTT camera HDR off / with Post-process Layer

Game View / RTT camera HDR on / with Post-process Layer

Game View / RTT camera HDR on / without Post-process Layer

Aha! Yes, this is an important point of data.

There’s a Keep Alpha setting you’ll want to enable, but it’s a feature that’s regularly broken when HDR is also enabled. The fix is … there isn’t one because while there are ways to modify the post processing stack’s shaders to ensure the alpha doesn’t get nuked, it usually also breaks anti-aliasing.

Though one option you do have is disable anti-aliasing in the stack and render at a slightly too high resolution for the intended use.

Hi,

yeah, sorry for leaving the post processing out. I just realized it was an issue when I wrote down the step by step guide to reproduce the problem. Mea culpa.

After revisiting my settings, it turns out I have been stupid. In my graphics settings the HDR was set to R11G11B10 instead of FP16. After changing this, I could apply your solution and use FXAA with the ‘Keep Alpha’ box ticked in my post processing layer for the RTT camera.

This resolved all my issues. I can now use HDR colors properly and also the Standard/Particles Unlit shader behaves like it should.

Thanks for your help.

3 Likes

You saved a lot of time for many people including myself.

This post was so incredibly helpful thank you, I was going insane.

9832176--1414197--upload_2024-5-13_11-47-55.png

Recap / Visuals:
Blend SrcAlpha OneMinusSrcAlpha
Using this for the render shader allows it to correctly render in the world and to any RenderTexture with the correct tone.

The second target is a PNG save from a RenderTexture which received the first material, rendered with the Blend SrcAlpha OneMinusSrcAlpha, One OneMinusSrcAlpha premultiply shader rules.

Those RenderTextures or their saved textures will look incorrect when previewed in editor or when rendered with any other material than the premultiply shader, as shown by the third target.

Other (probably worse) premultiply options:

I’ve found that there are compatible Shader Graph options in URP such as Sprite Unlit Premultiply, which seems to work fine with some brief testing.

There is also a “Legacy Particles Alpha Blended Premulitply” shader included which seems to render it okay.