It’s been a while since I completed my project related to this, so things aren’t that fresh in my head anymore. Plus, I suppose there have been various changes / improvements to ThreeJS since working with the 149 revision the last time, so I’m not sure this is 100% accurate or up to date, but…
Here are the relevant portions of my depth fragment shader code, used with a composer:
...
uniform sampler2D depthSampler;
uniform mat4 proj;
uniform mat4 view;
uniform vec3 eyePos;
uniform float eyeNear;
uniform float eyeFar;
varying vec2 UV;
...
float remap(float value, float getmin, float getmax, float setmin, float setmax)
{
return setmin + (value - getmin) * (setmax - setmin) / (getmax - getmin);
}
float logarithmicDepthToViewZ(float logdepth, float near, float far)
{
return 1.0 - exp2(logdepth * log(far + 1.0) / log(2.0));
}
float perspectiveDepthToViewZ(float invClipZ, float near, float far)
{
return (near * far) / ((far - near) * invClipZ - far);
}
float viewZToOrthographicDepth(float viewZ, float near, float far)
{
return (viewZ + near) / (near - far);
}
float orthographicDepth(float rawdepth, float near, float far)
{
#if defined(USE_LOGDEPTHBUF) && defined(USE_LOGDEPTHBUF_EXT)
rawdepth = logarithmicDepthToViewZ(rawdepth, near, far);
#else
rawdepth = perspectiveDepthToViewZ(rawdepth, near, far);
#endif
return viewZToOrthographicDepth(rawdepth, near, far);
}
vec3 wPosition(vec2 UV, float ortdepth, float near, float far)
{
vec4 ndpos = vec4(UV * 2.0 - 1.0, 0.0, 1.0);
vec4 vspos = inverse(proj) * ndpos;
vspos.xyz *= remap(ortdepth, 0.0, 1.0, near, far);
vec4 wspos = inverse(view) * vec4(vspos.xyz, 1.0);
return wspos.xyz;
}
...
void main()
{
...
float rawDepth = texture2D(depthSampler, UV).x;
float ortDepth = orthographicDepth(rawDepth, eyeNear, eyeFar);
vec3 geoWPosition = wPosition(UV, ortDepth, eyeNear, eyeFar);
...
}
with the uniforms coming from (just copy pasted part of my code for setting up the effect composer):
...
depthrender = new THREE.WebGLRenderTarget(Width, Height, {depthTexture: new THREE.DepthTexture({type: THREE.FloatType}), samples: 0});
composer = new EffectComposer(renderer, depthrender);
composer.setSize(Width, Height);
var renderpass = new RenderPass(scene, camera);
composer.addPass(renderpass);
var depthpass = new ShaderPass(depthShader);
if (camera) {camera.updateMatrix(); camera.updateMatrixWorld(); camera.updateProjectionMatrix();};
try {depthpass.uniforms.depthSampler.value = depthrender.depthTexture;} catch {};
try {depthpass.uniforms.proj.value = camera.projectionMatrix;} catch {};
try {depthpass.uniforms.view.value = camera.matrixWorldInverse;} catch {};
try {depthpass.uniforms.eyePos.value = camera.position;} catch {};
try {depthpass.uniforms.eyeNear.value = camera.near;} catch {};
try {depthpass.uniforms.eyeFar.value = camera.far;} catch {};
...
composer.addPass(depthpass);
...
So, as far as I recall, getting the perspective depth from view Z wasn’t what I needed, as the conversion formulas are a bit different from those for the orthographic (aka linear) depth, see here too. Anyway, it was plenty of guesswork for me too until I got to the desired result. Hope the above helps in answering your questions - if not, maybe someone more knowledgeable can correct me if I’m wrong, since, as I said, it’s been a while since I worked with these.