Спасибо, помогло. Получил точность порядка 0.001. Возможно, я раньше где-то косячил

А, ещё в openGL z значение меняется от -1 до 1 (), лучше сразу в вершинном шейдере делать z = z*0.5+0.5, в пиксельном от этого точность теряется.
Матрицу трогать не стал, так как отсечение работает именно от -1 до 1.
кусочек кода, помогший в отладке, может, кому пригодится:
если расстояние отличается очень сильно, рисует белым, иначе оттенками синего или красного в зависимости от знака разницы.
float delta = - vInv.z + unpack(texture2D(uDepthMap, vInv.xy));
delta *= 1000.0;
if (abs(delta)>1.0){
gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
return;
}
if (delta>0.0){
gl_FragColor = vec4(delta, 0.0, 0.0, 1.0);
} else if (delta < 0.0) {
gl_FragColor = vec4(0.0, 0.0, -delta, 1.0);
} else {
gl_FragColor = uColorAmbient*(1.0+vInv.w) + uColorDiffuse * nn;
}
где разница > 1/2000, на картинке белое.