Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
  • Help Room /
avatar image
0
Question by heyx3 · Nov 06, 2018 at 02:08 AM · shadershader programmingworldspacedepthdepth-buffer

I'm trying to calculate the world-space position in a shader using the camera's depth buffer. I'm getting values that vary a lot based on the camera's rotation. Why?

The world-space distance between the camera and a fragment shouldn't change at all as the camera rotates, but I have been running into this problem where it does change. I've made a simple example to demonstrate.

Below is a view of a landscape with hills and a mountain. The landscape is rendered with a post-process effect (shader code is below) that visualizes the reconstructed world-space distance from the camera's depth texture, snapped to discrete intervals to make the problem clearer:

alt text

Here is where the problem comes in: when I rotate my camera and objects move to the side of the view, their world-space distance shrinks by hundreds of meters (watch the mountain and large hill as they move to the right):

alt text

Why are these depth values changing so dramatically? My depth visualization shader is below.

 Shader "Visualize Depth PostProcess"
 {
     Properties
     {
         _Range("Range", Float) = 2575
     }
     SubShader
     {
         Tags { "RenderType"="Opaque" }
 
         Pass
         {
             CGPROGRAM
             #pragma vertex vert
             #pragma fragment frag
 
             #include "UnityCG.cginc"
 
 
             struct appdata
             {
                 float4 vertex : POSITION;
             };
             struct v2f
             {
                 float4 vertex : SV_POSITION;
                 float4 screenPos : TEXCOORD0;
             };
 
             v2f vert (appdata v)
             {
                 v2f o;
                 o.vertex = UnityObjectToClipPos(v.vertex);
                 o.screenPos = ComputeScreenPos(o.vertex);
                 return o;
             }
 
             float _Range;
             sampler2D_float _CameraDepthTexture;
 
             fixed4 frag (v2f IN) : SV_Target
             {
                 float4 depthMapUV4 = UNITY_PROJ_COORD(IN.screenPos);
                 float rawDepth = tex2Dproj(_CameraDepthTexture, depthMapUV4).r;
 
                 float camToFragWorldDist = LinearEyeDepth(rawDepth);
                 float3 color = saturate(camToFragWorldDist / _Range).xxx;
 
                 //To make the effect more stark, snap the depth value to discrete steps.
                 return float4((0.2 * step(0.1, color)) +
                                 (0.2 * step(0.3, color)) +
                                 (0.2 * step(0.5, color)) +
                                 (0.2 * step(0.7, color)) +
                                 (0.2 * step(0.9, color)),
                               1);
             }
             ENDCG
         }
     }
 }
 


problem2.png (10.9 kB)
problem4.png (13.5 kB)
Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

1 Reply

· Add your reply
  • Sort: 
avatar image
0
Best Answer

Answer by heyx3 · Nov 17, 2018 at 05:23 AM

OK I'm pretty certain I've fixed this problem. At the very least, I've compensated for it so that the artifact from camera rotation isn't visible.

I thought that the output from LinearEyeDepth was the view-space distance to the fragment (and therefore, the world-space distance). However, it is merely the view-space Z component from the camera to the fragment; I was ignoring the view-space X and Y! The true distance is found by doing this:

 float2 viewPosXY = ...;
 float viewPosZ = LinearEyeDepth(sampledDepth);
 return length(float3(viewPosXY, viewPosZ));

After some time, I figured out how to calculate viewPosXY in the fragment shader so that I could finally calculate the above expression.

  1. Output the clip-space position from the vertex shader (i.e. UnityObjectToClipPos(v.vertex))

  2. Also output the screen position for sampling the depth texture (i.e. ComputeScreenPos(UnityObjectToClipPos(v.vertex));)

  3. In the fragment shader, do the perspective division for the clip-space position: float2 clipPosXY = IN.clipPos.xy/IN.clipPos.w;

  4. Sample the depth texture and convert to linear eye depth: float viewPosZ = LinearEyeDepth(tex2Dproj(_CameraDepthTexture, UNITY_PROJ_COORD(IN.clipPos))).r;

  5. You could also get the depth value by lerping between the camera's near and far plane using Linear01Depth(sampledDepth) as the t value. The results are slightly different, and I'm not sure which one is more mathematically correct (or what the difference between them really is). Using the LinearEyeDepth approach should be more performant because it doesn't have that extra lerp.

  6. Get the view-space X and Y, given the clip-space X and Y and the view-space Z (this part is taken from the Unity docs):

float camAspectRatio = ...; // =width/height. Has to be fed in from script

float camFOVDegrees = ...; //Has to be fed in from script.

const float deg2rad = 0.0174533

float viewHeight = 2.0 * viewPosZ * tan(camFOVDegrees * 0.5 * deg2rad);

float viewPosY = 0.5 * viewHeight * clipPosXY.y,

viewPosX = 0.5 * viewHeight * clipPosXY.x * camAspectRatio;

It seems to me like you should also be able to get the view-space X and Y much more easily by calculating mul(UNITY_MATRIX_MV, v.vertex), but for some reason that gives me very strange results.

Finally, compute the distance:

float worldSpaceDist = length(float3(viewPosX, viewPosY, viewPosZ));

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

216 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

i wanna draw inside like outside. shader.... 1 Answer

Getting Color Generated from Shader to Script to Shader 0 Answers

A public list of color in shader. 0 Answers

What is the difference between Semantic POSITION and SV_POSITION both 0 Answers

How do i get a shader to affect every object with the same material? 0 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges