Author Topic: UISprite not rendered to RenderTexture alpha while UITexture/UILabel are  (Read 5150 times)

bac9

  • Full Member
  • ***
  • Thank You
  • -Given: 2
  • -Receive: 4
  • Posts: 113
    • View Profile
I'm encountering a pretty strange problem. My UI camera is rendering to a texture which I then use in a material applied to a curved surface attached to a player. It's a standard approach for UI rendering with Oculus, Elite-style world space UI and other use cases like that. Everything works fine, except for one little thing - for some strange reason, not a single UISprite is written to the alpha of that RenderTexture. All UITexture and UILabel objects are rendered perfectly, but sprites vanish. To illustrate:

Original UI:



What I get in the render texture:



I'm not sure what could be the reason for that, frankly.

  • I have checked the source textures, the problem still appears when you use an image that works with UITexture on a UISprite, so it's not an issue with all-black alpha in a source
  • UITextures don't have a custom shader/material, so they are rendered through exact same shader atlased sprites do, which rules out issue with the shaders

Any ideas?

If that helps, I'm using a 3D UI prefab NGUI creates from the menu with minimal changes. UI camera is using Solid Color clear mode with the alpha of the background color set to zero (it's the only clearing configuration that works properly with render textures, anything else will leave trash from the previous frames in the texture).

_____________________________

Edit: Looks like I overlooked the shader difference between UITexture and UISprite - the latter is using premultiplied shader. Can you fill me in on why can't premultiplier shader be rendered into texture and what would I lose by switching the atlas to unlit colored shader used by UITexture by default?
« Last Edit: September 19, 2014, 06:36:35 PM by bac9 »

Nicki

  • Global Moderator
  • Hero Member
  • *****
  • Thank You
  • -Given: 33
  • -Receive: 141
  • Posts: 1,768
    • View Profile
Re: UISprite not rendered to RenderTexture alpha while UITexture/UILabel are
« Reply #1 on: September 19, 2014, 06:35:45 PM »
Oh hey, I think I saw a sweet video of this on /r/Unity3D. :)

I generally tend to have issues with the alphas with rendertextures, so make absolutely sure nothing is happening with that. Remember that the UIDrawCall makes a instance of the material so if you're doing anything funky after the fact, it may not carry through.

Try to have one of the UITextures use a custom material that uses TransparentColored, just to see if that also vanishes. Try to use a panel the clips/doesn't clip and see if that changes anything.

bac9

  • Full Member
  • ***
  • Thank You
  • -Given: 2
  • -Receive: 4
  • Posts: 113
    • View Profile
Re: UISprite not rendered to RenderTexture alpha while UITexture/UILabel are
« Reply #2 on: September 19, 2014, 06:38:19 PM »
: )

Yeah, I already pinned the issue down to premultiplied shaders not actually creating any alpha output. Standard transparent shaders used by UITexture work.
Can you tell me what am I losing quality wise if I were to switch to non-premultiplied shaders? Or it's only a matter of saving texture size (RGB vs RGBA) and being compliant with some mobile hardware?

Edit: Erm... yeah, it's not as simple as I thought. Changing the shader on the altas material has no effect. I guess I need to reimport it?
Edit 2: Okay, a big problem - a black sprite with 50% alpha writes 50% background color + 50% black into RGB of the render texture instead of 100% black, which kills the look of every single semi-transparent element. :(



Edit 3: This can be hidden if you can agree to only use one color for every semi-transparent UI element ever - by setting the clear color of the camera to that color, ensuring that RGB values rendered to texture will stay right. In my case, with black semi-transparent frame fills, that would be setting the camera clear color to black. But that's not ideal as I'd prefer camera clear color to be white, to avoid black leaking into predominantly white UI pixels.

Edit 4: I wonder if the issue can be resolved by creating a custom NGUI shader that writes proper transparency to alpha while refusing to actually display that transparency for the camera when there are no other pixels rendered using that shader underneath, rendering sprite color at full intensity in that case. That will lead to completely proper colors being fed to the RenderTexture, but doing so indiscriminately will kill any and all overlays, potentially leading to background sprites overwriting white text with black in render texture RGB, and other nasty issues. I'm not sure if it's possible to do right.
« Last Edit: September 19, 2014, 07:00:47 PM by bac9 »

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: UISprite not rendered to RenderTexture alpha while UITexture/UILabel are
« Reply #3 on: September 19, 2014, 08:46:12 PM »
I don't advise using PMA shaders. They have no noticeable benefit on current hardware. PMA shaders handle alpha differently. Pre-multiplied alpha assumes that your RGB channel was already modulated by your alpha channel, so the lower the alpha, the blacker the color in the RGB channel. NGUI handles this for you when you add a new sprite to the atlas that's using a PMA shader.

I advise creating an atlas without using a PMA shader. Stick to Unlit/Transparent Colored instead. Some of your textures will most likely have to change, however.

bac9

  • Full Member
  • ***
  • Thank You
  • -Given: 2
  • -Receive: 4
  • Posts: 113
    • View Profile
Re: UISprite not rendered to RenderTexture alpha while UITexture/UILabel are
« Reply #4 on: September 20, 2014, 07:48:16 AM »
Okay. How can I disable pre-modulation of the RGB by the alpha channel in the atlas maker? As far as I see, there is no such option.
Or it's not influencing the quality of sprites even if I'm using a Transparent Colored shader, which means I only have to directly edit the material settings of the atlas without touching atlas maker at all (which assigns PMA by default)?

Aside from that, the question of getting semi-transparent sprite colors correctly rendered into RGB of a render texture (without mixing with clear color, see the last edits and a screenshot above) still stands - how can I achieve that?

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: UISprite not rendered to RenderTexture alpha while UITexture/UILabel are
« Reply #5 on: September 20, 2014, 09:26:05 AM »
It's done automatically if the shader used by the atlas is PMA. Change the shader on its material to Unlit/Transparent Colored and re-add your sprites.

Your textures should be pure white. Only alpha channel should have data.