Hello, I am using a shader on a render texture. I only want that effect, if the vertex is in range of a specific point in the scene. For that to work, I need to know the original world position of that vertex/pixel. As far as I can tell, I need to calculate from the screenspace back to worldspace. For that I guess I need something like a Camera2World and projection matrix that I give via scipt to the shader, aswell as the depth to that pixel from the camera and then... do some calculations. However, I am at a loss at what matrix I need to give to the shader exactly, how to get the depth to a pixel and how to calculate it properly. I tried to use camera.cameraToWorldMatrix together with something like LinearEyeDepth of the _CameraDepthTexture, but I can't seem to get it to work. I find it really difficult to debug shaders :/ Any help would be much appreciated. Thank you!
To find the world space position of a pixel in a post-processing shader (which is how I read this scenario), you can find the view-space positions of the 4 far-plane frustum corners in the vertex shader (so that they will be blended per-fragment, thus giving us per-pixel view directions). Multiplying this by [0,1] linear depth gives you the view-space position of the pixel, which can then be transformed to world space, i.e; Code (CG): ... float4x4 _InvProjectionMatrix; //Pass this in via 'camera.projectionMatrix.inverse' float4x4 _ViewToWorld; //Pass this in via 'camera.cameraToWorldMatrix' struct v2f { float4 pos : SV_POSITION; float2 uv : TEXCOORD0; float4 viewDir : TEXCOORD1; }; v2f vert (appdata v) { v2f o; o.pos = UnityObjectToClipPos (v.vertex); o.uv = v.uv; o.viewDir = mul (_InvProjectionMatrix, float4 (o.uv * 2.0 - 1.0, 1.0, 1.0)); return o; } half4 frag (v2f i) : SV_Target { float depth = Linear01Depth (tex2D (_CameraDepthTexture, i.uv).r); //Perspective divide and scale by depth to get view-space position float3 viewPos = (i.viewDir.xyz / i.viewDir.w) * depth; //Transform to world space float3 worldPos = mul (_ViewToWorld, float4 (viewPos, 1)); //Fill a sphere around the origin return 1.0 - saturate (distance (0, worldPos)); } ...
Thank you so very much! You not only understood my question, but also provided a perfect answer. This line was the deal breaker in my previous attempts: Code (CSharp): o.viewDir = mul (_InvProjectionMatrix, float4 (o.uv * 2.0 - 1.0, 1.0, 1.0)); I couldn't get it to work the way it should. My math was wrong somehow. Thanks again!