Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Could use some help–short VertexLit shader transparency issues

Discussion in 'Shaders' started by cj-currie, Apr 8, 2011.

  1. cj-currie

    cj-currie

    Joined:
    Nov 27, 2008
    Posts:
    301
    Hi folks,

    I'm not as good at writing shaders, but I came up with a short one to render transparent objects in correct order. Because it's sprite-based, I only need vertex lighting.



    Problem is that at certain distances from the camera, parts of the object will stop rendering transparency correctly, looking instead like some kind of weird jpeg. On right you can see the object at a closer distance, but on left you can see what happens as it moves into the weird range.

    Can anyone help shed some light on what's going on? Here's the code:

    Code (csharp):
    1. Shader "Transparent/VertexLit DoubleSided" {
    2.     Properties {
    3.         _Color ("Main Color", Color) = (1,1,1,1)
    4.         _MainTex ("Base (RGB) Trans (A)", 2D) = "white" {}
    5.     }
    6.  
    7.     SubShader {
    8.  
    9.         Tags {"Queue"="Transparent" "RenderType"="Transparent"}
    10.        
    11.         //Pass {ColorMask 0}
    12.        
    13.         Pass {
    14.            
    15.             AlphaTest Greater .1
    16.             ZWrite on
    17.             Blend SrcAlpha OneMinusSrcAlpha
    18.             ColorMask RGB
    19.    
    20.             Material {
    21.                 Diffuse [_Color]
    22.                 Ambient [_Color]   
    23.             }
    24.        
    25.             Lighting On
    26.             SetTexture [_MainTex] {
    27.                 Combine texture * primary DOUBLE, texture * primary
    28.             }
    29.         }
    30.     }
    31. }
     
  2. Jessy

    Jessy

    Joined:
    Jun 7, 2007
    Posts:
    7,325
    Are you sure lighting makes any sense at all? Are you using point lights? I could see it making some sense there.

    I can't tell what I'm looking at in your screenshots. It looks like there's some bug demon whose texture extends way past his silhouette, and has compression artifacts in the alpha channel, with an inappropriate color in RGB. You want to upload a problem graphic maybe?
     
  3. cj-currie

    cj-currie

    Joined:
    Nov 27, 2008
    Posts:
    301
    Sure. here's the source image, which will be a spritesheet when completed (not my work).

    http://img858.imageshack.us/i/lavaform.png/

    However, this artifact problem applies to every object that uses this shader in my scene. The scene uses a directional light (I will use tinting later on, which is why it's VertexLit and not Lighting Off).
     
  4. Jessy

    Jessy

    Joined:
    Jun 7, 2007
    Posts:
    7,325
    A directional light on a flat mesh is the same thing as ambient light multiplied by a 0-1 value. You're probably better off leaving lighting off and using SetGlobalColor, although I'm not sure of the performance impact of that, versus utilizing only ambient light, which is easier, as it's already a global value in Unity.

    Anyway, I don't know what's going on with the white sparkly bit over the water, because I don't have compression artifacts on my computer in that area. (What compression type are you using? I tried DXT5 and PVRTC 2bpp, without the issue in either case.) But the other issue is caused by the lava beast being renderer prior to the water. (Is that a composite? It would be weird if the left and right halves rendered differently, and seems an impossibility to me. Unless maybe those are different tiles underneath?) I assume you have your camera set to clear to solid black, which yields that very strong shadow. You just need to do whatever's necessary to ensure proper rendering order.
     
  5. cj-currie

    cj-currie

    Joined:
    Nov 27, 2008
    Posts:
    301
    Ah, I did forget about RenderSettings.ambientLight – thanks. Though that screenshot above was from already from a light-less scene (I forgot I'd done that).

    The sparkly bit is part of the water tileset.

    If you move the lava beast 1 meter to the right the shadow line stays still – it's a border that's in relation to the camera.

    I knew it had something to do with sorting, since manually handling the renderQueue solves the problem (but adds extra work at load time). Since it seemed to be related to distance from the camera (or perhaps viewing angle?) I was wondering if the problem were with a setting in my shader.
     
  6. Jessy

    Jessy

    Joined:
    Jun 7, 2007
    Posts:
    7,325
    Objects in the transparent queue are sorted based on the centers of their AABBs, in relation to the camera. So it's to be expected that you'll have shifting of rendering order as either the camera, or transparent objects move around.
     
  7. cj-currie

    cj-currie

    Joined:
    Nov 27, 2008
    Posts:
    301
    What would you say the best way to set that order is? RenderQueue?
     
  8. Jessy

    Jessy

    Joined:
    Jun 7, 2007
    Posts:
    7,325
    If you're going to be using the same shader with multiple materials, yes. That way, you won't need to have multiple versions of the same shader (aside from queue), in a build. But if you're finding yourself having nearly as many shaders as you have materials, like I sometimes do, then you can just hardcode the values.

    http://unity3d.com/support/documentation/Components/SL-SubshaderTags.html
     
  9. cj-currie

    cj-currie

    Joined:
    Nov 27, 2008
    Posts:
    301
    Damn, that's what I was afraid of. I have many objects (all of which use the same shader) and some move nearer and farther from the camera periodically. I wish there were some way to do the sorting in the shader by accessing the object's transform properties. I guess I'll just have to watch out for when objects pass each other and keep track of the sort order myself, then?
     
  10. Jessy

    Jessy

    Joined:
    Jun 7, 2007
    Posts:
    7,325
    I don't know what you've got going on in your scene, but I would think it would be as simple as linking up a set of renderQueue's to transform.position.z in LateUpdate. You should be able to use LINQ, with an array of transforms and materials, to make that pretty concise.
     
  11. cj-currie

    cj-currie

    Joined:
    Nov 27, 2008
    Posts:
    301
    My old method (before I tried to rewrite the shader) did just that, storing the materials in a Hashtable.