Hi, I'm making custom shader with dynamic light emission and encountered problems with meta pass not taking into account world space data, neither its own mesh nor data passed from a script. Here is very basic example. Create Unity built-in Standard shader and add emission to be taken from the object 'worldPos' Code (CSharp): Shader "Custom/Meta_Standard" { Properties { _Color ("Color", Color) = (1,1,1,1) _MainTex ("Albedo (RGB)", 2D) = "white" {} _Glossiness ("Smoothness", Range(0,1)) = 0.5 _Metallic ("Metallic", Range(0,1)) = 0.0 _Emission("Emission", float) = 1 } SubShader { Tags { "RenderType"="Opaque" } LOD 200 CGPROGRAM // Physically based Standard lighting model, and enable shadows on all light types #pragma surface surf Standard fullforwardshadows // Use shader model 3.0 target, to get nicer looking lighting #pragma target 3.0 sampler2D _MainTex; struct Input { float2 uv_MainTex; float3 worldPos; }; half _Glossiness; half _Metallic; fixed4 _Color; float _Emission; void surf (Input IN, inout SurfaceOutputStandard o) { // Albedo comes from a texture tinted by color fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color; o.Albedo = c.rgb; // Metallic and smoothness come from slider variables o.Metallic = _Metallic; o.Smoothness = _Glossiness; o.Alpha = c.a; o.Emission = IN.worldPos * _Emission; } ENDCG } FallBack "Diffuse" } And the result is this: All spheres emit same color, even those that are in completely negative coordinates and must have 0 emission. Same result if writing custom meta pass. Everything here is calculated in light-map space. Code (CSharp): Pass { Name "META" Tags { "LightMode"="Meta" } CGPROGRAM #pragma vertex vert #pragma fragment frag #define UNITY_PASS_META #include "UnityCG.cginc" #include "UnityMetaPass.cginc" float _Emission; struct appdata { float4 vertex : POSITION; float2 texcoord1 : TEXCOORD0; float2 texcoord2 : TEXCOORD1; }; struct v2f { float4 vertex : SV_POSITION; float3 worldPos : TEXCOORD0; }; float4 MetaVertexPosition(float4 vertex, float2 uv1, float2 uv2, float4 lightmapST, float4 dynlightmapST) { if (unity_MetaVertexControl.x) { vertex.xy = uv1 * lightmapST.xy + lightmapST.zw; // OpenGL right now needs to actually use incoming vertex position, // so use it in a very dummy way vertex.z = vertex.z > 0 ? 1.0e-4f : 0.0f; } if (unity_MetaVertexControl.y) { vertex.xy = uv2 * dynlightmapST.xy + dynlightmapST.zw; // OpenGL right now needs to actually use incoming vertex position, // so use it in a very dummy way vertex.z = vertex.z > 0 ? 1.0e-4f : 0.0f; } return vertex; } v2f vert (appdata IN) { v2f o; float4 vertex = MetaVertexPosition(IN.vertex, IN.texcoord1.xy, IN.texcoord2.xy, unity_LightmapST, unity_DynamicLightmapST); o.vertex = UnityObjectToClipPos(vertex); o.worldPos = mul(unity_ObjectToWorld, IN.vertex); //o.worldPos = mul(unity_ObjectToWorld, vertex); return o; } fixed4 frag (v2f i) : SV_Target { fixed4 c = fixed4(i.worldPos, 1); UnityMetaInput metaIN; UNITY_INITIALIZE_OUTPUT(UnityMetaInput, metaIN); metaIN.Albedo = c.rgb; metaIN.Emission = c.rgb * _Emission; return UnityMetaFragment(metaIN); } ENDCG } Even if I first take vertex position from light-map space and then transforming it into world space (line 58), results are always wrong. Above example is very simple, beside mesh worldPos I have to find solution to work with non-mesh data inside meta pass, like camera world space position and other info that is passed from script. So, how do I supply meta pass with world space data?
Hm, your shader seems to do what you're telling it to do, but the range of the world position from 0 to 1 is quite small. I added a tiling size and let it tile just to see the effect everywhere. Here is the modified shader: Code (CSharp): Shader "Custom/Meta_Standard" { Properties { _Color("Color", Color) = (1,1,1,1) _MainTex("Albedo (RGB)", 2D) = "white" {} _Glossiness("Smoothness", Range(0,1)) = 0.5 _Metallic("Metallic", Range(0,1)) = 0.0 _EmissionTiling("EmissionTiling", Range(0.1, 20)) = 10 _Emission("Emission", float) = 1 } SubShader { Tags{ "RenderType" = "Opaque" } LOD 200 CGPROGRAM // Physically based Standard lighting model, and enable shadows on all light types #pragma surface surf Standard fullforwardshadows // Use shader model 3.0 target, to get nicer looking lighting #pragma target 3.0 sampler2D _MainTex; struct Input { float2 uv_MainTex; float3 worldPos; }; half _Glossiness; half _Metallic; fixed4 _Color; fixed _Emission; half _EmissionTiling; void surf(Input IN, inout SurfaceOutputStandard o) { // Albedo comes from a texture tinted by color fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color; o.Albedo = c.rgb; // Metallic and smoothness come from slider variables o.Metallic = _Metallic; o.Smoothness = _Glossiness; o.Alpha = c.a; o.Emission = frac(IN.worldPos / _EmissionTiling) * _Emission; } ENDCG } FallBack "Diffuse" } And that's the result: As for your second question: You can set values of a shader by either providing a property block or directly set vectors: https://docs.unity3d.com/ScriptReference/Shader.SetGlobalVector.html