根据glm::项目输出计算z缓冲区
Calculating z-buffer from glm::project output
我想根据glm::project的输出计算对象位置的z缓冲区。以下代码中z缓冲区的计算来自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。根据wiki页面,该值应介于-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,则上面的值将与存储在深度缓冲区中的值不同。
您将维基百科文章中的公式应用于错误的值。您已经使用glm::project应用了投影矩阵,这就是z' = ...
公式的作用。所以你基本上在代码中应用了两次投影矩阵。
OpenGL中的深度缓冲区值在窗口坐标中,它们在范围[n,f]内,其中n和f是使用glDepthRange(n, f)
设置的(默认值为0和1)。您可以在规范的13.6.1中阅读它。这些值与投影矩阵中使用的zNear和zFar值无关。
glm::project
只是假设这些默认值,并且由于它输出窗口坐标,所以这是写入深度缓冲区的值。所以正确的代码很简单:
float zBufferValue = screenCoords.z;
- 为什么"do while"循环不断退出,即使条件计算结果为 false?
- C++字符*缓冲区的大小
- 递归函数计算序列中的平方和(并输出过程)
- (C++)分析树以计算返回错误值的简单算术表达式
- 我的字符计数代码计算错误.为什么
- 在计算中使用二的幂有多有利可图
- 为什么msgrcv()将垃圾字符馈送到缓冲区
- 如何用尽可能少的数据将数据缓冲区计算为零校验和值
- 计算着色器不写入缓冲区?
- GLSL 计算着色器 使用查找表设置缓冲区会导致不写入任何数据,与其他数据设置相同的缓冲区有效
- 计算着色器不写入缓冲区
- QML:读取由计算着色器操作的缓冲区
- 计算gpu前缓冲区中像素的平均值,而无需将前缓冲区复制回系统内存
- 如何计算帧缓冲区间距
- 从缓冲区指针计算堆栈中的返回地址
- 对于 DirectX 11,我可以做些什么来不计算每个渲染()中的缓冲区
- 将顶点缓冲区绑定到计算着色器以修改数据
- 为什么 glDrawElements 在使用相同的缓冲区进行计算着色和渲染时会干扰 glGetBufferSubData
- C++ 3 台计算机上的缓冲区溢出不同
- 根据glm::项目输出计算z缓冲区