Search Unity

Lit particle shader comes out as gray instead of white?

Discussion in 'General Graphics' started by _eternal, Aug 17, 2021.

  1. _eternal

    _eternal

    Joined:
    Nov 25, 2014
    Posts:
    304
    I'm trying to set up a lit dust particle in a 2D game. I haven't really worked with 3D before, so my understanding of lighting and the built-in shaders is limited.

    So, this is my material setup. Pretty straightforward. For simplicity's sake, I thought I'd use a Legacy particle shader, but note that I observed the same problem with the Particles/Standard Surface shader.



    For testing purposes, I set the Particle System's Start Color to (1,1,1,1), and I disabled Color Over Time.

    This is how it looks in the game (cropped, because it's a small particle system).


    And this is my dust texture. This is the raw png, so it looks invisible on this page, but you can open it in a new tab.



    As you can see, the particle appears more gray than white, even though the source texture is mostly white.

    From what I understand, this happens because I'm using a lit shader - that's what google tells me. But that still doesn't make sense to me, because:
    1. For testing, the scene's Ambient Color is currently set to (1,1,1,1), so the lighting shouldn't really affect the sprites right now
    2. I use the Sprites/Diffuse shader on all my sprites. When the scene's Ambient Color is set to white, these sprites appear exactly as they would with an unlit shader - they only change color if I change the Ambient Color
    I know that there are a couple of workarounds, but they don't work for me, because:
    1. I don't want to use Additive blending, because it's a dust particle. It looks too glowy with Additive. Alpha Blend makes more sense here.
    2. I still want the shader to be lit so that it will work in other situations in the game. In this particular case, I'm turning the scene's Ambient Color way down as part of a puzzle; the scene turns mostly black, and you have to navigate by using some torches. I try to stick with lit shaders for the whole game so that effects like this can work out of the box.
    3. I can't use the Emission property, because this will ignore the scene's Ambient Color (and thus break the puzzle described above)
    The only workaround I found was to use the standard shader and compensate for the grayness by turning up HDR intensity in the albedo, but that's obviously not the correct or intended solution.

    I mean, at the end of the day, I think the Sprites/Diffuse shader might do what I want, although I haven't properly tested it yet.

    Still, I must be fundamentally misunderstanding something about these built-in particle shaders, because I've had this issue many times in the past. The additive and unlit particle shaders work as expected, but I have never figured out how the lit + alpha blend ones are supposed to work. Whether Legacy or Standard or even custom, they always come out gray instead of white.
     
  2. _eternal

    _eternal

    Joined:
    Nov 25, 2014
    Posts:
    304
    I submitted this as a bug report just out of curiosity, and they wrote back with the most comically pointless explanation I've ever seen:

    "Shaders perform calculations to determine the colour of pixels on the screen. That's why the particle colour appears to be different when changing its Shader."

    And then they linked me to the Shader Introduction page in the manual.

    At the end of the day, I'm still not sure why alpha blended lit particles come out differently than Sprites/Diffuse particles. You'd think that the alpha blend shader would only apply ambient light, but there must be something else going on that I don't understand. Nowadays I just use Sprites/Diffuse for everything unless I have a specific reason not to.

    Just leaving this here for posterity and as a warning for newbie devs: please, don't use the "bug report" feature in the engine. This is the second time I've seen Unity QA give copy-pasted responses instead of actually reading and responding to the problem like a human being. Granted, this one isn't a bug per se, but I'm not sure if it's a feature either.

    Either way, I've seen QA drop the ball twice now, so this lesson has been learned. Just stick to the forums and ask other devs, or hope an engineer shows up (they're pretty good). But the bug report system feels like you're talking to Uber or Amazon or any other publicly traded company.
     
  3. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,352
    Their explanation, while terse and unhelpful, was correct though.

    The Mobile/Particles/VertexLit Blended shader is also old and terrible, and that's just how it happens to calculate lighting. It's one of the few shaders that still uses the now deprecated vertex lit rendering path that Unity still includes with the editor.

    The Particles/Standard Surface shader set to Rendering Mode > Fade is likely closer to what you want. The Sprite/Diffuse will also work pretty well. But the reality is Unity does not ship a good lit particle shader for translucent materials. All of the shaders it ships with calculate lighting as if the surface is solid. Fine if you want your particles to be flying chunks of wood or rocks, terrible if you want smoke, dust, or steam.

    For those kinds of particles to get something that doesn't look terrible you'd have to write your own shader, get one from the asset store, or search around to see if anyone has released one for free (I don't know of any). Proper lighting on transparent media is really, really hard and expensive, so there's a million different levels of hacks and approximations you can use to get there. Unity's just happen to be roughly the cheapest option.

    One trick is to use one of the two shaders I mentioned above and play with the Renderer > Normal Direction setting on the particle system. Try setting it to 0.5.
     
    _eternal likes this.
  4. _eternal

    _eternal

    Joined:
    Nov 25, 2014
    Posts:
    304
    Thanks for the explanation. I hadn't seen the Normal Direction setting before; I see the particle changing color in Scene mode but not in Game mode.

    Weirdly enough, even this opaque cloud sprite displays as gray in the Game view for me, although it displays correctly in the Scene view. That's with Particles/Standard Surface set to Fade. Meanwhile, it displays exactly like the source sprite when I use the Sprite/Diffuse shader.

    There's not much VFX in my project anyway, but we do need lit shaders because I use Ambient Light in a few situations. For our use case, it seems that Sprite/Diffuse is the safest bet because it's the most faithful to the original sprite. It's strange that the particle shaders that Unity ships with can't accout for this seemingly simple use case, but I guess my conclusion is... maybe I didn't really need particle shaders in the first place? And if I did, I could possibly get by with something from the asset store.