DX11 tessellation, custom lighting problem

Hi!

Has anyone encountered with this problem?

  1. Switch deferred rendering in player settings and use DX11.
  2. Make two sphere (left, right on the picture).
  3. Apply the built-in “Tessellation/Bumped Specular (smooth)” shader on the left sphere.
  4. Apply the exact same shader like the “Tessellation/Bumped Specular (smooth)” shader to the right sphere, but write in the shader this parameter: “exclude_path:prepass”.
  5. The problem is self explanatory. (tweak the smoothness settings to make the artifacts visible)

If I use this second shader on characters the artifacts always visible, no matter how I tweak the settings.
I would be really happy if anyone could help me. :slight_smile:

Thx.

1231530--51874--$DX11CustomLighting.jpg

Yes, unfortunately. Lost much time trying to find a workaround, to no avail.

It’s not tessellation specific, actually.
When deferred lighting is enabled unity seems to do an additional pass (shadow receiver? early-z?) that affects even objects that have forward only lighting model.
This pass is not affected by vertex displacement and pops-out resulting in visual artifacts.
Tried also bisecting the compiled surface shader to pinpoint the issue: the pass in question is NOT present.

What also seems to me the same issue happens with transparent (including cutout) forward-only shaders with deferred enabled.

https://fogbugz.unity3d.com/default.asp?529908_km84u6oc3mc23se5

http://answers.unity3d.com/questions/149283/vertex-displacement-in-forward-rendering-shader.html

Edit: unlike what i wrote in the bug report it does happen in Unity 3 IIRC.

I’ve found two temporary workaround! :slight_smile:

  1. Use at the tags the following: “Queue” = “Transparent-1” LINK
    Be careful it might cause rendering issues. (e.g. something rendering in front/behind your model)

  2. Use “Offset -1,-1” in the shader. LINK
    It gives quite acceptable result from distance, maybe good for somebody.

I know these are not perfect solutions but better than nothing. :wink:

The issue is likely from the shadow pass not being set up to do the same tesselation as your regular shader.

You’ll have to add custom shadow collector/receiver passes that perform the same tesselation as your regular shader.

Unfortunately it doesn’t solve the issue, since the offending pass is NOT part of the shader itself, but something unity does when deferred lighting is active.

You can try it yourself with this shader. As you can see there’s only one pass and it should display the object in in red and translated by 0.1 in x axis.
With deferred lighting enabled the object itself renders as expected, including the shadows if you decomment the caster/receiver block, but there’s a second object beside it showing skybox color.

Shader "Custom/Displacement" {
	Properties {
        _Color ("Color", color) = (1,1,1,0)
    }
    SubShader {
        Tags { "RenderType"="Opaque" }
        LOD 300

		Pass {
			Name "Red"
			Tags { "LightMode" = "Always" }
			
			Fog {Mode Off}
			ZWrite On ZTest LEqual Cull Off
	
			CGPROGRAM
				#pragma vertex vert
				#pragma fragment frag
				#pragma fragmentoption ARB_precision_hint_fastest
				#pragma multi_compile_particles
	
				#include "UnityCG.cginc"
				
				struct appdata {
					float4 vertex : POSITION;
				};
	
				struct v2f {
					float4 vertex : POSITION;
				};
	
				v2f vert(appdata v) {
	           		v.vertex.x += 0.1;
	           		
					v2f o;
					o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
					return o;
				}
				
				fixed4 frag (v2f i) : COLOR {
					return fixed4(1, 0, 0, 1);
				}
			ENDCG
		}
        
/*
		// Pass to render object as a shadow caster
		Pass {
			Name "ShadowCaster"
			Tags { "LightMode" = "ShadowCaster" }
			
			Fog {Mode Off}
			ZWrite On ZTest LEqual Cull Off
			Offset 1, 1
	
			CGPROGRAM
				#pragma vertex vert
				#pragma fragment frag
				#pragma multi_compile_shadowcaster
				#pragma fragmentoption ARB_precision_hint_fastest
				#pragma exclude_renderers d3d11_9x
				#include "UnityCG.cginc"
				
				struct v2f { 
					V2F_SHADOW_CASTER;
				};
				
				v2f vert( appdata_full v ) {
	           		v.vertex.x += 0.1;
	            				
					v2f o;
					TRANSFER_SHADOW_CASTER(o)
					return o;
				}
				
				float4 frag( v2f i ) : COLOR {
					SHADOW_CASTER_FRAGMENT(i)
				}
			ENDCG
		}
		
		// Pass to render object as a shadow collector
		Pass {
			Name "ShadowCollector"
			Tags { "LightMode" = "ShadowCollector" }
			
			Fog {Mode Off}
			ZWrite On ZTest LEqual
	
			CGPROGRAM
				#pragma vertex vert
				#pragma fragment frag
				#pragma fragmentoption ARB_precision_hint_fastest
				#pragma exclude_renderers d3d11_9x
				#pragma multi_compile_shadowcollector
				
				#define SHADOW_COLLECTOR_PASS
				#include "UnityCG.cginc"
				
				struct appdata {
					float4 vertex : POSITION;
				};
				
				struct v2f {
					V2F_SHADOW_COLLECTOR;
				};
				
				v2f vert (appdata_full v) {
	           		v.vertex.x += 0.1;
	            				
					v2f o;
					TRANSFER_SHADOW_COLLECTOR(o)
					return o;
				}
				
				fixed4 frag (v2f i) : COLOR {
					SHADOW_COLLECTOR_FRAGMENT(i)
				}
			ENDCG
		}
*/
		
    }
    FallBack Off
}

1234449--52253--$forward_disp_bug3.png

Since Unity kinda states in documentation that forward and deferred can be mixed I consider this simpy a bug.

Just found a workaround inspired by Emptiness’ response, though I’m still testing.
Just render in Geometry+1!

Tags { "RenderType"="Geometry+1" } :smiley:

Edit: forget what I said above. As you can see I mistook the tag. Though it works in transparent queue or with custom RenderType value as in the code above (“Geometry+1” is not a standard render type), but it has other consequences making the workaround pretty useless. :frowning:

I’m still waiting for a final solution. :slight_smile:
Does anyone has a good idea?

thx

i think my issue is directly related to this one except that mine also is present in 3.5.
http://forum.unity3d.com/threads/187452-artifacts-using-custom-lighting-model-amp-pragma-glsl-w-deferred-lighting

From another thread for more info:

Also, even if I disable shadows globally in quality setting the issue is still threre.

the above code is not a DirectX 11 shader , so how can it have tessellation?

it says #pragma exclude_renderers d3d11_9x

There are multiple target platforms in Unity for DirectX 11. d3d11_9x is used for Windows RT, and d3d11 is used for the desktop version of Windows. The distinction is made because Windows RT is used for ARM processors, in stead of x86 processors.

So when you exclude the d3d11_9x platform, it can still be compiled for ‘regular’ DX11.

we’re in 4.5 now this problem is still there… it’s mind blowing how everything in unity is broken when you try to push it a bit…

there does seem to be a loss of focus as of late. still love unity though.

The fix is to remove this:

FallBack “Diffuse”

If you need the fallbacks for the ShadowCasters, just add them yourself.

Sorry, but it’s not enough. To quote myself:

Btw. for those who didn’t know yet, it’s fixed in Unity 5.

Ah, I was using Unity 5, so that’s probably why!