我想根据 glm::project 的输出计算对象位置的 z 缓冲区。下面代码中z-buffer的计算来自https://en.wikipedia.org/wiki/Z-buffering .
我尝试过的
int windowWidth = 800;
int windowHeight = 600;
float positions[] = {-42.5806f, 27.8838f, 49.9729f} // Example point
glm::mat4 model;
glm::mat4 view;
glm::mat4 proj;
view = glm::lookAt(
glm::vec3( 0.0f, 0.0f, 2.0f ),
glm::vec3( 0.0f, 0.0f, 0.0f ),
glm::vec3( 0.0f, 1.0f, 0.0f )
);
proj = glm::perspective( 45.0f, aspect, 0.1f, 10.0f );
// Get screen coordinates from an object point
glm::vec3 screenCoords = glm::project(
glm::vec3( positions[0], positions[1] , positions[2] ),
view*model,
proj,
glm::vec4( 0, 0, windowWidth, windowHeight )
);
// Calculating the z-buffer
int zFar = 10;
int zNear = 0.1;
float zBufferValue = (zFar+zNear ) / ( zFar-zNear ) + ( 1/screenCoords.z) * ( ( -2*zFar*zNear ) / ( zFar - zNear ) );
问题
无论我如何旋转模型或使用哪个点,zBufferValue 的值都是 1。根据维基页面,该值应介于 -1(近平面)和 1(远平面)之间。
我的计算有什么问题吗?
最佳答案
您的最后一行代码是多余的。深度计算是在投影变换(以及随后的透视划分)期间完成的。 glm::project
的本质是这样的:
// P: projection matrix
// MV: modelview matrix
// v: vertex to convert to screen space
vec4 result = P * MV * vec4(v, 1.0f);
result /= result.w; // perspective divide
// convert X/Y/Z from normalized device coords to screen coords...
result.z = (result.z + 1.0f) * 0.5f;
// ...
return vec3(result);
它还将 X/Y 坐标从标准化设备空间 [(-1, -1), (1, 1)]
转换为屏幕空间 [(0, 0), (viewport_width, viewport_height)]
但由于您只关心深度缓冲区,所以我在上面省略了这一步。
因此忽略代码的最后 3 行,screenCoords.z
应该包含一个与您从 glReadPixels 中获得的值相同的深度缓冲区值.
当然,存储在显卡上的实际位数取决于深度缓冲区的大小以及 OpenGL 的使用设置。特别是,如果您使用自定义 glDepthRange上面的值将与深度缓冲区中存储的值不同。
关于c++ - 从 glm::project 输出计算 z-buffer,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17251858/