GLSL 从相机获取特定像素的距离?

GLSL get pixel-specific distance from camera?

我正在尝试获取绘制到顶点着色器中 canvas 的每个像素的距离。顶点着色器代码如下:

attribute vec4 modelVertexPosition;

// cameraMatrix is strictly used as a ref to the camera's position in this case
// and does not contribute to the screen projection position calculation
uniform mat4 cameraMatrix;
uniform mat4 projectionMatrix;
uniform mat4 modelMatrix;

varying float cameraDistance;

void main(void) {
  // calc world position of vertex
  vec4 vertexPosition = modelMatrix * modelVertexPosition;
  // calc frustum position of vertex
  vec4 projVertexPosition = projectionMatrix * vertexPosition;
  gl_Position = projVertexPosition;
  // set cameraDistance varying for fragment shader
  cameraDistance = distance(cameraMatrix[3].xyz, (modelMatrix * scaledModelVertexPosition).xyz);
}

这适用于严格位于所绘制三角形顶点上的所有点,但很明显 glsl 正在对三角形内的点相对于其顶点的距离进行线性插值。这通常不是什么大问题,但当相机比顶点更靠近三角形的中间时,它尤其明显。

为了演示这个问题,我将片段着色器设置为将形状的亮度设置为该点距相机距离的函数,越暗越近。我设置了一种情况,暴露了执行方法的缺陷,如下所示:

所以这就引出了一个问题,有没有办法得到每个像素距离相机的位置?

免责声明:我对 OpenGL 框架还是很陌生,实际上我只是在试验 WebGL 的简化版本,所以对我的解决方案持保留态度。另外,如果有人有更好的方法,我会洗耳恭听。

无论如何,我发现只有片段着色器能够进行单个像素计算。相反,顶点着色器通过计算每个顶点的着色器的所有输出,然后使用插值来估计顶点之间的所有像素的输出来假设顶点之间的所有像素。

考虑到这一点,只需将计算相机距离的代码移动到片段着色器,就可以在每个像素的基础上进行计算,这就是我在这种情况下想要的效果。但是我假设这种方法效率低得多,所以这种方法应该只在绝对必要的时候使用(据我估计)。

再次强调,如果大家对这个话题有更深入的了解,欢迎补充,欢迎批评指正。

片元到相机的距离与其在深度缓冲区中的深度有关。您可以按如下方式在片段着色器中计算深度:

float depth = gl_Position.z / gl_Position.w;

可见片段的深度从0到1不等,0在近裁剪平面上,1在远裁剪平面上。您可以使用以下公式计算与相机的距离:

depth = (1/camera_distance - 1/near)/(1/far - 1/near)

请注意,深度和相机距离不是线性相关的。相反,深度与 1/camera_distance 线性相关。 OpenGL 等使用相机距离的 倒数 定义“深度”,因此硬件可以对屏幕中的三角形进行“深度”的线性插值 space 以快速确定每个三角形可见透视图中的像素。