Why doesn't PixelOrVertex work?

Hey Guys

I am trying to add a Pass with “LightMode” = “VertexOrPixel” or “PixelOrNone” placed after 3 “LightMode” = “Pixel” Passes.

The resulting pass produced very strange behaviour, basically its turned off and just flickers on occasionally as you move the camera around. The pass ONLY works if I set it to “Pixel” which isn’t ideal as the last pass only acts as a LightMap/Cloud Shadows multiplicative pass.

Is there any way to execute a Pass only ONCE after all the “Pixel” passes have gone thru???

if you set it to pixel, it will only work in pixel.

It makes no sense to fire it up with vertex because you will get visual problems at the border where it switches from pixel to vertex lighting then as it switches from present to gone.

I guess what you are looking for is having different subshaders to handle it for pixel shader environment as well as for fixed function pipeline / vertex lighting

Thats not really what I’m after. In truth I am only using the Pixel light mode to implement shadows. My vertex light mode passes use exactly the same code base (Programmable Pipeline) BUT don’t include the Shadowing macros. I am never using the Fixed Function Pipeline.

I want my 3 normal passes to execute for each Pixel Light like normal(Pixel Lightmode), and than have 1 pass that is multiplicative AFTER them, but I want it to execute only ONCE, it doesn’t make sense to execute PER light. The PixelOrVertex lightmode suggests this is possible but it doesn’t work.

Don’t know what the docs suggest or where.
But its known that you can not mix pixel light and vertex light behavior at the same time as they will fight each other on the hardware.

Its naturally possible that I’m not fully understanding you, though the common posting behavior when having a problem is posting the sources so people see on the spot what you did and potentially see as well what was meant to be done.

Here is the Shader.
It works as it is… but if you change the last Pass to LightMode : PixelOrNone or PixelOrVertex, it all goes wrong. Oddly, you can use PixelOrNone BEFORE Pixel passes (like the ambient pass) but not afterwards.

Shader "UberSplat" 
{
	Properties 
	{
		_Color ("Main Color", Color) = (1,1,1,1)
		_MainTex ("Base (RGB)", 2D) = "white" {}	
		_Splat1 ("Splat Map 1-3 (RGBA)", 2D) = "black" {}
		_Splat2 ("Splat Map 4-6(RGBA)", 2D) = "black" {}
		_Splat3 ("Splat Map 7-9 (RGBA)", 2D) = "black" {}
		_Splat4 ("Splat Map 10-12(RGBA)", 2D) = "black" {}	
		_MainTex1 ("Texture 1 (RGB)", 2D) = "white" {}
		_MainTex2 ("Texture 2 (RGB)", 2D) = "white" {}
		_MainTex3 ("Texture 3 (RGB)", 2D) = "white" {}
		_MainTex4 ("Texture 4 (RGB)", 2D) = "white" {}
		_MainTex5 ("Texture 5 (RGB)", 2D) = "white" {}
		_MainTex6 ("Texture 6 (RGB)", 2D) = "white" {}
		_MainTex7 ("Texture 7 (RGB)", 2D) = "white" {}
		_MainTex8 ("Texture 8 (RGB)", 2D) = "white" {}
		_MainTex9 ("Texture 9 (RGB)", 2D) = "white" {}
		_MainTex10 ("Texture 10 (RGB)", 2D) = "white" {}
		_MainTex11 ("Texture 11 (RGB)", 2D) = "white" {}
		_MainTex12 ("Texture 12 (RGB)", 2D) = "white" {}	
		_CloudMap ("CloudMap (RGB)", 2D) = "white" {}
		_CloudShadowsAlpha ("CloudShadowsAlpha", Float) = 0.75
	}

	Category 
	{
		Tags { "RenderType"="Opaque" }
		Blend AppSrcAdd AppDstAdd
		Fog { Color [_AddFog] }
		Fog { Mode Exp2 }
		SubShader 
		{	
			// ---------------------------------------------------
			// Textures 1 - 3
			// ---------------------------------------------------
			Pass 
			{
				Name "PPL"
				Tags { "LightMode" = "Pixel" }
				CGPROGRAM
				#pragma vertex vert
				#pragma fragment frag
				#pragma multi_compile_builtin
				//#pragma fragmentoption ARB_fog_exp2
				#pragma fragmentoption ARB_precision_hint_fastest
				#include "UnityCG.cginc"
				#include "AutoLight.cginc"

				struct v2f 
				{
					V2F_POS_FOG;
					LIGHTING_COORDS
					float4 suv[2];
				};

				uniform sampler2D _MainTex1;
				uniform sampler2D _MainTex2;
				uniform sampler2D _MainTex3;
				uniform sampler2D _Splat1;
				uniform float4 _MainTex1_ST;
				uniform float4 _MainTex2_ST;
				uniform float4 _MainTex3_ST;

				v2f vert (appdata_base v)
				{
				v2f o;
					PositionFog( v.vertex, o.pos, o.fog );

					o.suv[0].xy = TRANSFORM_TEX(v.texcoord, _MainTex1);
					o.suv[0].zw = TRANSFORM_TEX(v.texcoord, _MainTex2);
					o.suv[1].xy = TRANSFORM_TEX(v.texcoord, _MainTex3);

					o.suv[1].z = (v.vertex.x + 1000.f) / 2000.f; // POSITION
					o.suv[1].w = (v.vertex.z + 1000.f) / 2000.f; // POSITION

					TRANSFER_VERTEX_TO_FRAGMENT(o);
					return o;
				}

				float4 frag (v2f i) : COLOR
				{
					half4 tex1 = tex2D( _MainTex1, i.suv[0].xy );
					half4 tex2 = tex2D( _MainTex2, i.suv[0].zw );
					half4 tex3 = tex2D( _MainTex3, i.suv[1].xy );
					half4 splat1 = tex2D( _Splat1, i.suv[1].zw); 

					half4 color;

					color = tex1 * splat1.r + 	
							tex2 * splat1.g + 
							tex3 * splat1.b;

					return color * LIGHT_ATTENUATION(i);
				}
				ENDCG
			}
			// Textures 4 - 6
			Pass 
			{
				Name "PPL"
				Tags { "LightMode" = "Pixel" }
				CGPROGRAM
				#pragma vertex vert
				#pragma fragment frag
				#pragma multi_compile_builtin
				//#pragma fragmentoption ARB_fog_exp2
				#pragma fragmentoption ARB_precision_hint_fastest
				#include "UnityCG.cginc"
				#include "AutoLight.cginc"

				struct v2f 
				{
					V2F_POS_FOG;
					LIGHTING_COORDS
					float4 suv[2];
				};

				uniform sampler2D _MainTex4;
				uniform sampler2D _MainTex5;
				uniform sampler2D _MainTex6;
				uniform sampler2D _Splat2;
				uniform float4 _MainTex4_ST;
				uniform float4 _MainTex5_ST;
				uniform float4 _MainTex6_ST;

				v2f vert (appdata_base v)
				{
					v2f o;
					PositionFog( v.vertex, o.pos, o.fog );

					o.suv[0].xy = TRANSFORM_TEX(v.texcoord, _MainTex4);
					o.suv[0].zw = TRANSFORM_TEX(v.texcoord, _MainTex5);
					o.suv[1].xy = TRANSFORM_TEX(v.texcoord, _MainTex6);

					o.suv[1].z = (v.vertex.x + 1000.f) / 2000.f; // POSITION
					o.suv[1].w = (v.vertex.z + 1000.f) / 2000.f; // POSITION

					TRANSFER_VERTEX_TO_FRAGMENT(o);
					return o;
				}

				float4 frag (v2f i) : COLOR
				{
					half4 tex4 = tex2D( _MainTex4, i.suv[0].xy );
					half4 tex5 = tex2D( _MainTex5, i.suv[0].zw );
					half4 tex6 = tex2D( _MainTex6, i.suv[1].xy );

					half4 splat2 = tex2D( _Splat2, i.suv[1].zw); 
					half4 color;

					color = tex4 * splat2.r + 	
							tex5 * splat2.g + 
							tex6 * splat2.b;

					return color * LIGHT_ATTENUATION(i);
				}
				ENDCG
			}
			// Textures 7 - 9
			Pass 
			{
				Name "PPL"
				Tags { "LightMode" = "Pixel" }
				CGPROGRAM
				#pragma vertex vert
				#pragma fragment frag
				#pragma multi_compile_builtin
				//#pragma fragmentoption ARB_fog_exp2
				#pragma fragmentoption ARB_precision_hint_fastest
				#include "UnityCG.cginc"
				#include "AutoLight.cginc"

				struct v2f 
				{
					V2F_POS_FOG;
					LIGHTING_COORDS
					float4 suv[2];
				};

				uniform sampler2D _MainTex7;
				uniform sampler2D _MainTex8;
				uniform sampler2D _MainTex9;

				uniform sampler2D _Splat3;

				uniform float4 _MainTex7_ST;
				uniform float4 _MainTex8_ST;
				uniform float4 _MainTex9_ST;

				v2f vert (appdata_base v)
				{
				v2f o;
				PositionFog( v.vertex, o.pos, o.fog );

				o.suv[0].xy = TRANSFORM_TEX(v.texcoord, _MainTex7);
				o.suv[0].zw = TRANSFORM_TEX(v.texcoord, _MainTex8);
				o.suv[1].xy = TRANSFORM_TEX(v.texcoord, _MainTex9);

				o.suv[1].z = (v.vertex.x + 1000.f) / 2000.f; // POSITION
				o.suv[1].w = (v.vertex.z + 1000.f) / 2000.f; // POSITION

				TRANSFER_VERTEX_TO_FRAGMENT(o);
				return o;
				}

				float4 frag (v2f i) : COLOR
				{
					half4 tex7 = tex2D( _MainTex7, i.suv[0].xy );
					half4 tex8 = tex2D( _MainTex8, i.suv[0].zw );
					half4 tex9 = tex2D( _MainTex9, i.suv[1].xy );

					half4 splat3 = tex2D( _Splat3, i.suv[1].zw); 
					half4 color;

					color = tex7 * splat3.r + 	
							tex8 * splat3.g + 
							tex9 * splat3.b;

					return color * LIGHT_ATTENUATION(i);
				}
				ENDCG
			}
			// Textures 10 - 12
			Pass 
			{
				Name "PPL"
				Tags { "LightMode" = "Pixel" }
				CGPROGRAM
				#pragma vertex vert
				#pragma fragment frag
				#pragma multi_compile_builtin
				//#pragma fragmentoption ARB_fog_exp2
				#pragma fragmentoption ARB_precision_hint_fastest
				#include "UnityCG.cginc"
				#include "AutoLight.cginc"

				struct v2f 
				{
					V2F_POS_FOG;
					LIGHTING_COORDS
					float4 suv[4];
				};

				uniform sampler2D _MainTex10;
				uniform sampler2D _MainTex11;
				uniform sampler2D _MainTex12;
				uniform sampler2D _Splat4;
				uniform float4 _MainTex10_ST;
				uniform float4 _MainTex11_ST;
				uniform float4 _MainTex12_ST;

				v2f vert (appdata_base v)
				{
					v2f o;
					PositionFog( v.vertex, o.pos, o.fog );

					o.suv[0].xy = TRANSFORM_TEX(v.texcoord, _MainTex10);
					o.suv[0].zw = TRANSFORM_TEX(v.texcoord, _MainTex11);
					o.suv[1].xy = TRANSFORM_TEX(v.texcoord, _MainTex12);

					o.suv[1].z = (v.vertex.x + 1000.f) / 2000.f; // POSITION
					o.suv[1].w = (v.vertex.z + 1000.f) / 2000.f; // POSITION

					TRANSFER_VERTEX_TO_FRAGMENT(o);
					return o;
				}

				float4 frag (v2f i) : COLOR
				{
					half4 tex10 = tex2D( _MainTex10, i.suv[0].xy );
					half4 tex11 = tex2D( _MainTex11, i.suv[0].zw );
					half4 tex12 = tex2D( _MainTex12, i.suv[1].xy );

					half4 splat4 = tex2D( _Splat4, i.suv[1].zw); 
					half4 color;

					color = tex10 * splat4.r + 	
							tex11 * splat4.g + 
							tex12 * splat4.b;

					return color * LIGHT_ATTENUATION(i);
				}
				ENDCG
			}
			// ------------- LIGHT MAP  CLOUD SHADOWS ---------------
			Pass 
			{
				Tags {"LightMode" = "Pixel"}
				Blend DstColor Zero
				Fog { Mode Exp2 }
				Fog { Color (1,1,1,1) }

				CGPROGRAM
				#pragma vertex vert
				#pragma fragment frag
				#pragma fragmentoption ARB_fog_exp2
				#include "UnityCG.cginc"

				uniform sampler2D _CloudMap;
				uniform float _CloudShadowsAlpha;

				struct v2f 
				{
					float4 pos : POSITION;
					float2 uv : TEXCOORD0;
				};
				struct a2v
				{
					float4 vertex : POSITION;
					float3 normal : NORMAL;
					float4 texcoord : TEXCOORD0;
				};

				v2f vert (a2v v)
				{			
					v2f o;
					o.pos = mul(glstate.matrix.mvp, v.vertex);
					o.uv.x = (v.vertex.x + 1000.f) / 2000.f;
					o.uv.y = (v.vertex.y + 1000.f) / 2000.f + (_Time[0] * 0.15);
					return o;
				};
				half4 frag( v2f i ) : COLOR
				{									
					float cloudShadows = tex2D( _CloudMap, i.uv).g;

					half4 color = 1.f;
					color = 1.0 - (cloudShadows * _CloudShadowsAlpha);
								
					return color;
				}
				ENDCG
			}
		}
	}
	Fallback "VertexLit", 2
}

Your shader shouldn’t show any flickering due to mixing pipelines, as it only uses the programmable pipeline. I believe dreamora is conflating vertex lighting with the fixed function pipeline.

I’m a little confused as to what you want from using VertexOrPixel or PixelOrNone in the last pass. Since it multiplies the its output with the existing destination colour, and in the absence of pixel lights it would be the only pass, the output would depend on whatever colour already occupied the frame buffer.

Finally, although it’s great that you’ve provided source code, finding or creating enough relevant source textures to set up the shader would be a chore, so I haven’t played around with it myself.

I assumed a combiner to be used if no pixel light is beeing used, so yes you are right :slight_smile: