# How can I transform a world space point to a camera's screen coordinate?

I'm trying to transform a point in fragment shader from world space to screen coordinate of a second camera. Not the main one.

I think I know how to achieve that to the main camera, but I'm struggling to find an easy way to transform a point in world space to screen coordinate of camera2.

• There is no such thing as "camera 1" and "camera 2" in a shader. There is only the current camera. Commented Jan 3, 2019 at 23:12
• @Draco18s that's not necessarily a barrier, it just means it's up to us to define what we mean by "camera 2" in how we write our shaders and C# scripts. ;) Commented Jan 4, 2019 at 2:22

First, we can make a shader that exposes a variable for the view-projection matrix of the camera we want to project "into"...

struct appdata
{
float4 vertex : POSITION;
};

struct v2f
{
float3 worldPosition : TEXCOORD0;
float4 vertex : SV_POSITION;
};

sampler2D _MainTex;

// Here we've defined a new variable we can put
// our second camera's projection info into.
float4x4 _CameraMatrix;

v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.worldPosition = mul(unity_ObjectToWorld, v.vertex).xyz;
return o;
}

fixed4 frag (v2f i) : SV_Target
{
// Map world position into camera's projected coordinates.
float4 projected = mul(_CameraMatrix, float4(i.worldPosition, 1.0f));

// Perform perspective divide and adjust range
// from NDC's -1...1 to UV space's 0...1
float2 uv = (projected.xy / projected.w) * 0.5f + 0.5f;

// Sample a texture with this UV to prove it works.
fixed4 col = tex2D(_MainTex, uv);
return col;
}


Next, we attach a script to that camera to tell it to upload its matrix into that variable each frame before rendering time:

[RequireComponent(typeof(Camera))]
public class PerspectiveToShader : MonoBehaviour {

public Material materialToModify;
public string matrixVariableName;

new Camera camera;
int matrixVariable;

void OnEnable () {
camera = GetComponent<Camera>();
}

void LateUpdate () {
var viewProjection = camera.nonJitteredProjectionMatrix * transform.worldToLocalMatrix;

materialToModify.SetMatrix(matrixVariable, viewProjection);
}
}


If you need this across many materials, you can instead set it with Shader.SetGlobalMatrix instead of piping it into each material individually.

• Thanks DMGregory. Thant's exactly what i'm looking for. May god grant you good health, knowledge, guidance, wisdom and success. Commented Jan 4, 2019 at 10:02