gpt4 book ai didi

java - 将 OpenGL 深度缓冲区转换为距相机的世界空间 z 距离?

转载 作者:行者123 更新时间:2023-12-02 00:34:41 24 4
gpt4 key购买 nike

我正在使用 Java OpenGL(JOGL 2.x,从 Git 源构建)。我正在将场景渲染到带有颜色和深度附件的帧缓冲区对象。我想将 [0,1] 深度缓冲区值转换为世界空间距离。我的深度附件定义如下:

    private void setupDepthFBOs(GL2 gl,
int width,
int height,
int[] frameBufferIds,
int[] colorBufferIds,
int[] depthBufferIds) {
// based on
// http://www.java2s.com/Code/Java/Advanced-Graphics/BloomOpenGL.htm
// generate a framebuffer object
gl.glGenFramebuffers(1, frameBufferIds, 0);
// bind the framebuffer
gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, frameBufferIds[0]);

// generate a texture in memory
gl.glGenTextures(1, colorBufferIds,0);
gl.glBindTexture(GL2.GL_TEXTURE_2D, colorBufferIds[0]);
// this will be an RGBA texture (4 bpp) with width, height..
gl.glTexImage2D(GL2.GL_TEXTURE_2D, // target texture type
0, // mipmap LOD level
GL2.GL_RGBA8, // internal pixel format
width, // width of generated image
height, // height of generated image
0, // border of image
GL2.GL_RGBA, // external pixel format
GL2.GL_UNSIGNED_BYTE, // datatype for each value
null); // buffer to store the texture in memory

// set some texture parameters?
gl.glTexParameteri(GL.GL_TEXTURE_2D,
GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR);

// use the texture we just created in the framebuffer we just created
gl.glFramebufferTexture2D(
GL2.GL_FRAMEBUFFER, // target texture type
GL.GL_COLOR_ATTACHMENT0, // attachment point
GL.GL_TEXTURE_2D, // texture target type
colorBufferIds[0], // on-gpu id for texture
0); // mipmap lod level

gl.glGenTextures(1,depthBufferIds,0);
gl.glBindTexture(GL.GL_TEXTURE_2D,depthBufferIds[0]);
gl.glTexImage2D(GL2.GL_TEXTURE_2D, // target texture type
0, // mipmap LOD level
GL2.GL_DEPTH_COMPONENT24, // internal pixel format
//GL2.GL_DEPTH_COMPONENT
width, // width of generated image
height, // height of generated image
0, // border of image
GL2.GL_DEPTH_COMPONENT, // external pixel format
GL2.GL_UNSIGNED_INT, // datatype for each value
null); // buffer to store the texture in memory


gl.glTexParameteri(GL.GL_TEXTURE_2D,
GL.GL_TEXTURE_MIN_FILTER, GL.GL_NEAREST);
gl.glTexParameteri(GL.GL_TEXTURE_2D,
GL.GL_TEXTURE_MAG_FILTER, GL.GL_NEAREST);
gl.glTexParameteri(GL.GL_TEXTURE_2D,
GL.GL_TEXTURE_WRAP_S, GL.GL_CLAMP_TO_EDGE);
gl.glTexParameteri(GL.GL_TEXTURE_2D,
GL.GL_TEXTURE_WRAP_T, GL.GL_CLAMP_TO_EDGE);

gl.glFramebufferTexture2D(GL.GL_FRAMEBUFFER,
GL.GL_DEPTH_ATTACHMENT,
GL.GL_TEXTURE_2D,
depthBufferIds[0],0);


gl.glBindTexture(GL.GL_TEXTURE_2D, 0);

int status = gl.glCheckFramebufferStatus(GL2.GL_FRAMEBUFFER);


if (status == GL2.GL_FRAMEBUFFER_COMPLETE) {
gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, 0);
} else {
throw new IllegalStateException("Frame Buffer Object not created. Status was: " + status);
}

}

这成功创建了一个深度缓冲区,我可以将其作为纹理读取并渲染到屏幕上,或者用作着色器的输入(我预期的最终用例)。

前几天晚上在 IRC 上进行了一些讨论后,我得出了以下公式,将投影矩阵(此处表示为 p)和深度缓冲区值与世界空间中屏幕上每个点的距离相关联:

z = (p_33)/(p_34 + 深度)

(注意:我的投影矩阵/眼睛设置为朝 Z+ 方向看)

这会产生几乎正常的 z 值,但到场景中已知点的距离与该方程返回的值之间存在很大的误差范围。

你知道我在这里可能做错了什么吗?

最佳答案

这是我的计算,我的结果与你的不同:

定义:

depth = out_z / out_w
out_z = in_z * p_33 + in_w * p_43
out_w = in_z * p_34 + in_w * p_44

已知:

in_w = 1, p_43 = -1, p_44 = 0

工作:

depth = (in_z * p_33 - 1) / (in_z * p_34)
depth = p_33 / p_34 - 1 / (in_z * p_34)
p_33 / p_34 - depth = 1 / (in_z * p_34)
1 / (p_33 / p_34 - depth) = in_z * p_34
1 / (p_33 / p_34 - depth) = in_z * p_34
1 / (p_33 - depth * p_34) = in_z

关于java - 将 OpenGL 深度缓冲区转换为距相机的世界空间 z 距离?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8158347/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com