Search Unity

Light problem (pixelated/overexposed, no directional light) after 5.2.4 (up to the latest beta)

Discussion in 'Shaders' started by joergzdarsky, Apr 1, 2016.

  1. joergzdarsky

    joergzdarsky

    Joined:
    Sep 25, 2013
    Posts:
    56
    Hi,

    I have a huge problem with light in Unity and you are my only hope as I am completely stuck.
    I am working on a procedural space scene and a lot of objects are created manually / procedurally.
    Most of the elements (planet surfaces, asteroids, etc) are created in the same process:
    - Create a custom 224x224 mesh (a flat plane) on CPU
    - Calculate ComputeBuffers that include new 224x224 vertex positions (e.g. for a spherical noised plane) and a NormalMap in a ComputeShader
    - Render the mesh with custom shader and displace the positions of the original mesh's vertices with the one in the compute shader (this is done in the vertex shader) and apply the NormalMap (and a jpg texture, e.g. stone) in the SurfaceShader.

    I use directional light as this is the most reasonable for the space scenes.
    Thinks went pretty well up to Unity version 5.2.4. Below is an example of a few asteroids rendered.



    After this version and up to current 5.4.12b something seems to have changed drastically. Using directional light, the asteroids arent visible at all, no matter how I try to change the parameters of the directional light.

    Using point light, I manage to get at least something visible again, but really ugly looking. Overexposed, bad dark shadows, and especially very very pixelated.



    I have no idea how to fix this, and especially how I can move back to directional light? Can anybody help me or suggest what could go wrong currently? That would be very much appreciated!!

    This is the code of the shader in case the problem could be there.

    Code (CSharp):
    1. Shader "Custom/ProceduralPatch" {
    2.     Properties{
    3.         _MainTex("Albedo (RGB)", 2D) = "white" {}
    4.         _MaterialTex("Albedo (RGB)", 2D) = "white" {}
    5.         _NormalMap("_NormalMap", 2D) = "bump" {}
    6.         _Glossiness("Smoothness", Range(0,1)) = 0.5
    7.         _Metallic("Metallic", Range(0,1)) = 0.0
    8.     }
    9.     SubShader{
    10.         Tags{ "RenderType" = "Opaque" }
    11.         LOD 200
    12.  
    13.         CGPROGRAM
    14.  
    15.         #define nVerticesPerSide 224.0
    16.  
    17.         #include "UnityCG.cginc"
    18.         #include "noiseSimplexOptimized.cginc"
    19.  
    20.         #pragma surface surf Standard fullforwardshadows
    21.         #pragma vertex vert
    22.      
    23.         struct appdata_full_compute {
    24.             float4 vertex : POSITION;
    25.             float4 tangent : TANGENT;
    26.             float3 normal : NORMAL;
    27.             float4 texcoord : TEXCOORD0;
    28.             float4 texcoord1 : TEXCOORD1;
    29.             float4 texcoord2 : TEXCOORD2;
    30.             float4 texcoord3 : TEXCOORD3;
    31.             #if defined(SHADER_API_XBOX360)
    32.                 half4 texcoord4 : TEXCOORD4;
    33.                 half4 texcoord5 : TEXCOORD5;
    34.             #endif
    35.                 fixed4 color : COLOR;
    36.             #ifdef SHADER_API_D3D11
    37.                 uint id: SV_VertexID;
    38.             #endif
    39.         };
    40.  
    41.         struct OutputStruct {
    42.             float4 position;
    43.             float3 patchCenter;
    44.         };
    45.  
    46.         float globalNoise;
    47.  
    48.         #pragma target 5.0
    49.         sampler2D _MainTex;
    50.         sampler2D _MaterialTex;
    51.         sampler2D _NormalMap;
    52.  
    53.         #ifdef SHADER_API_D3D11
    54.                 StructuredBuffer<OutputStruct>    patchGeneratedFinalDataBuffer;
    55.         #endif
    56.  
    57.         struct Input {
    58.             float2 uv_MainTex;
    59.             float2 uv_MaterialTex;
    60.             float2 uv_NormalMap;
    61.             float3 worldPos;
    62.             float3 objPos;
    63.         };
    64.  
    65.         void vert(inout appdata_full_compute v, out Input o)
    66.         {
    67.             UNITY_INITIALIZE_OUTPUT(Input, o);
    68.             #ifdef SHADER_API_D3D11
    69.                 // Read Data from buffer
    70.                 float4 position = patchGeneratedFinalDataBuffer[v.id].position;
    71.                 float3 patchCenter = patchGeneratedFinalDataBuffer[v.id].patchCenter;
    72.  
    73.                 // Perform changes to the data
    74.                 // Translate the patch to its 'planet-space' center:
    75.                 position.xyz += patchCenter;
    76.  
    77.                 // Apply data
    78.                 v.vertex = float4(position);
    79.                 o.uv_MainTex = v.texcoord.xy;
    80.                 o.uv_MaterialTex = v.texcoord.xy;
    81.                 o.uv_NormalMap = v.texcoord.xy;
    82.                 o.worldPos = mul(unity_ObjectToWorld, v.vertex);
    83.                 o.objPos = v.vertex;
    84.             #endif
    85.         }
    86.  
    87.         half _Glossiness;
    88.         half _Metallic;
    89.         fixed4 _Color;
    90.      
    91.         void surf(Input IN, inout SurfaceOutputStandard o)
    92.         {
    93.             // Apply normal (remove for non-normalmapping)
    94.             fixed3 normal = tex2D(_NormalMap, IN.uv_NormalMap);
    95.             o.Normal = normal;
    96.  
    97.             // Add gridlines
    98.             //fixed4 c = terrainColor + gridLine + patchBorder;
    99.  
    100.             fixed3 crgb1 = tex2D(_MainTex, IN.uv_MainTex).rgb;
    101.             fixed3 crgb2 = tex2D(_MaterialTex, IN.uv_MaterialTex).rgb;
    102.             fixed4 c = fixed4(crgb2, 1);
    103.  
    104.             o.Albedo = c;
    105.             // Metallic and smoothness come from slider variables
    106.             o.Metallic = _Metallic;
    107.             o.Smoothness = _Glossiness;
    108.             o.Alpha = c.a;
    109.         }
    110.         ENDCG
    111.     }
    112. FallBack "Diffuse"
    113. }
    Code to draw the mesh:

    Code (CSharp):
    1. void OnRenderObject()
    2.     {
    3.         int QuadtreeTerrainRenderQueueCount = this.QuadtreeTerrainRenderQueue.Count;
    4.         int layer = LayerMask.NameToLayer(GlobalVariablesManager.Instance.layerLocalSpaceName);
    5.         // Render
    6.         for (int i = 0; i < QuadtreeTerrainRenderQueueCount; i++)
    7.         {
    8.             // Draw Mesh
    9.             Graphics.DrawMesh(this.QuadtreeTerrainRenderQueue[i].prototypeMesh, transform.localToWorldMatrix, this.QuadtreeTerrainRenderQueue[i].material, layer, null, 0, null, true, true);
    10.         }
    11.     }
    12.  
     
    Last edited: Apr 1, 2016
  2. cblarsen

    cblarsen

    Joined:
    Mar 10, 2007
    Posts:
    266
    I had a similar problem with a scene where all the objects were rendered with DrawMesh() instead of using a MeshRenderer. The lighting wouldn't change properly.

    I solved it by adding a dummy tiny cube. It seemed to trigger recalculation of the lighting, because a MeshRenderer was there.
     
  3. joergzdarsky

    joergzdarsky

    Joined:
    Sep 25, 2013
    Posts:
    56
    Hi cblarsen,

    thank you very much for your advice. I tried as you suggested ini different ways (add a cube object including a MeshRenderer, or add a MeshRenderer to the GameObject within which DrawMesh is called), but it didnt help. You can see a shirt "flicker" in the scene view once you apple the MeshRender, but the situation does not change it still looks pixelated like in the screenshot.
     
  4. cblarsen

    cblarsen

    Joined:
    Mar 10, 2007
    Posts:
    266
    Hmm. I overlooked the "pixelated" part. Are you using forward or deferred rendering?
    I wonder if you lost Antialiasing by switching to deferred somehow.
    Are you using any imageeffects, and is the problem still there without them?
     
  5. cblarsen

    cblarsen

    Joined:
    Mar 10, 2007
    Posts:
    266
    Another thing. In your shader, you read a normal out of a texture. I don't see you decoding that into a normal vector anywhere. Is the normal already coming from a texture with signed values, such as a ARGBHalf or ARGBFloat ?

    Edit:
    If not, you need to do
    Code (csharp):
    1.  
    2. o.Normal = UnpackNormal( normal );
    3.  
     
    Last edited: Apr 1, 2016
  6. joergzdarsky

    joergzdarsky

    Joined:
    Sep 25, 2013
    Posts:
    56
    The normalmap is previously created in the computeshader (which is responsible to calculate the vertex positions and the normals). Complete process is:
    1. Create a "prototype"-mesh on CPU (needed for the later DrawMesh() calls)
    2. Calculate vertex positions and normals in a ComputeShader (and store them in a ComputeBuffer)
    3. Set material with the ComputeBuffer and the NormalMap RenderTexture (material.SetBuffer() and material.SetTexture() )
    3. Call DrawMesh() using the prototype-Mesh and the material. In the materials shader I replace the vertex positions of the prototype mesh with the one from the buffer, and apply the normal, as mentioned previously.

    So in the ComputeShader in step 2 I create I calculate the float3 normal from the vertex positions, and store them in the RenderTexture.

    Script (where the normalmap reference is handed over to the compute shader)
    Code (CSharp):
    1. quadtreeTerrain.patchGeneratedNormalMapTexture = new RenderTexture(nPixelsPerEdge, nPixelsPerEdge, 0);
    2. quadtreeTerrain.patchGeneratedNormalMapTexture.enableRandomWrite = true;
    3. quadtreeTerrain.patchGeneratedNormalMapTexture.Create();
    4. ...
    5. quadtreeTerrain.material.SetTexture("_NormalMap", quadtreeTerrain.patchGeneratedNormalMapTexture);
    6.  
    ComputeShader:
    Code (CSharp):
    1.     // Create the Normal Map
    2.     float3 normalRGB = normal.xyz;
    3.     patchGeneratedNormalMapTexture[textureID] = float4(normalRGB,1);
    I think (not sure) UnpackNormal is not necessary in the surface shader later, at least it work until Unity 5.2.4 without, and if I add that, the whole mesh is rendered fully white.

    Good idea, but I have double checked it, there are none turned on. Just to make sure, I added a simple sphere in the scene. It is correctly lit, also by the Directional Light, while the procedural mesh is not drawn at all by the directional light or pixelated by the point light. The player is using forward light.




    No idea. I have the impression its something with the changes Unity did with light while switching to 5.3, but its tough to find out. Only idea what I could try is to move away from normalmapping to vertexnormals, for testing purposes if the issue is with the mapping.
     
    Last edited: Apr 2, 2016
  7. cblarsen

    cblarsen

    Joined:
    Mar 10, 2007
    Posts:
    266
    I think the problem is with a shadow or depth pass. (which as far as I know use the same code)
    Because you modify vertex positions a lot, you probably need an "addshadow" in your surface shader declaration. So it becomes:
    Code (csharp):
    1.  
    2.     #pragma surface surf Standard fullforwardshadows addshadow
    3.  
    If that still doesn't solve it, you could try sending me a unitypackage that reproduces the problem. If there is some secret sauce in your shader, that you don't want to show, maybe make a simplified version of it.
     
  8. joergzdarsky

    joergzdarsky

    Joined:
    Sep 25, 2013
    Posts:
    56
    Thank you cblarsen, very much appreciated. I added addshadow but the behavior is still the same. Really strange.

    I am going to modify my current unitypackage that works fine at 5.2.4 and throw away most of the other stuff / simplify the package. Not because of the secret sauce :), but to help finding the responsible classes easy and quick.

    So that package is testable then with the old version and as soon as its imported into a later version the issue occours.

    I thank you very much beforehand for the help!! Going to get in touch once I finished the package.