我正在为我正在开发的游戏构建一个小型 3D 引擎。我已经整理了我的基础知识:带有背面剔除的纹理三角形。然而,深度排序被证明是一个难题。
我通过平均构成三角形面的 3 个点来计算面 Z。较长的面有时会与较小的面重叠,因为它们具有较大的 Z 值,因此会在深度排序的显示列表中上升。
我该如何解决?如果我只能在编程时获得一些实际帮助,我确信存在已知的深度排序技术。我自己构建了渲染管道,所以我可以访问所有必需的数据 - 三角形、点、纹理、UV 坐标等。
以 3D 程序呈现的大教堂

在我的 3D 引擎中渲染的大教堂

似乎很难找到有关如何在连续渲染过程的着色器中访问深度和模板缓冲区的信息.
在第一个渲染过程中,我不仅渲染颜色和深度信息,还使用模板操作来计算对象.我为此使用了一个多渲染目标FBO,附带了颜色缓冲区和组合深度模板缓冲区.所有这些都是纹理的形式(没有涉及渲染缓冲对象).
在第二个渲染过程中(当渲染到屏幕时),我想基于每个像素访问先前计算的模板索引(但不一定是我正在绘制的相同像素),类似于您想要访问的先前渲染的颜色缓冲区以应用一些后期处理效果.
但是我没能将第二遍中的深度模板纹理绑定到我的着色器程序作为制服.至少只从中读取黑色值,所以我猜它没有正确绑定.
是否可以将深度模板纹理绑定到纹理单元以用于着色器程序?使用"普通"采样器是否无法访问深度和模板纹理?是否可以使用一些"特殊"采样器?它取决于在纹理或类似设置上设置的插值模式吗?
如果没有,在这两个渲染过程之间将模板信息复制到单独的颜色纹理中的最佳(最快)方法是什么?可能涉及使用模板测试绘制单一颜色的第三个渲染过程(我在最终渲染过程中只需要模板缓冲区的二进制版本,确切地说,我需要测试值是否为零).
中间FBO使用的纹理设置如下:
// The textures for color information (GL_COLOR_ATTACHMENT*):
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
// The texture for depth and stencil information (GL_DEPTH_STENCIL_ATTACHMENT*):
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, w, h, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, 0);
Run Code Online (Sandbox Code Playgroud)
在第二个渲染过程中,我目前只尝试"调试"所有纹理的内容.因此,我使用以下值设置着色器:
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, <texture>);
glUniform1i(texLocation, 0);
Run Code Online (Sandbox Code Playgroud)
让着色器程序只需将纹理复制到屏幕:
uniform sampler2D tex;
in vec2 texCoord;
out vec4 fragColor;
void main() {
fragColor = texture2D(tex, texCoord);
}
Run Code Online (Sandbox Code Playgroud)
结果如下:
当<texture>上面指的是我的一个颜色纹理时,我看到在第一个渲染过程中渲染的颜色输出,这是我所期望的.
当<texture>上面指深度模板纹理时,着色器不做任何事情(我看到用于清除屏幕的颜色).
将深度模板纹理复制到CPU并进行检查时,我会按预期在打包的24 + 8位数据中看到深度和模板信息.
我认为我不太了解 Unity 渲染引擎。
我使用RenderTexture生成截图(我需要稍后管理它):
screenshotRenderTexture = new RenderTexture(screenshot.width, screenshot.height, depthBufferBits, RenderTextureFormat.Default);
screenshotRenderTexture.Create();
RenderTexture currentRenderTexture = RenderTexture.active;
RenderTexture.active = screenshotRenderTexture;
Camera[] cams = Camera.allCameras;
System.Array.Sort(
cams,
delegate(Camera cam1, Camera cam2)
{
// It's easier than write float to int conversion that won't floor
// depth deltas under 1 to zero and will correctly work with NaNs
if (cam1.depth < cam2.depth)
return -1;
else if (cam1.depth > cam2.depth)
return 1;
else return 0;
}
);
foreach(Camera cam in cams)
{
cam.targetTexture = …Run Code Online (Sandbox Code Playgroud) 我有一个Flash应用程序,其中两个3d视图共享相同的Stage3DProxy,因为我需要一个在任何时候覆盖/绘制在另一个上.但是,它们似乎共享相同的3d空间/ z缓冲区(?).
我的更新功能目前看起来像这样:
private function onEnterFrame(event : Event) : void {
stage3DProxy.clear();
away3DView.render();
away3DView2.render();
stage3DProxy.present();
}
Run Code Online (Sandbox Code Playgroud)
显然,这本身还不够 - 我在某处读到了可以使用setDepthTest方法,例如:
stage3DProxy.context3D.setDepthTest(false, Context3DCompareMode.NEVER);
Run Code Online (Sandbox Code Playgroud)
...在每个视图的render()调用之间将它设置为不同的模式,但我对它的工作原理并不清楚,并且文档在实际上非常薄.我玩过,在渲染调用之间设置不同的东西,但没有快乐.
设置Stage3DProxy的唯一例子是使用一个Away3D视图和两个starling - 这不是我想要的.我在他们的论坛上阅读了一条评论,其中说你必须在大约'其他地方'指定某些setDepthTest设置,但是没有详细说明它们的位置或者它们需要设置的位置,这听起来像是一个非常黑客的应该是非常基本的东西!
如果有人可以提供帮助我会非常感激,或者如果有人知道另一种方法来做这件事 - 强迫一个特定的绘图顺序似乎应该是一个相对微不足道的任务但我发现没有任何有用的事情,我想坚持Away3D因为它是一个很好的API和功能集,但这是我当前项目的真正障碍!
提前致谢
我正在使用 OpenGL 制作 2D 游戏。我想做这样的绘图,首先我将要绘制的所有对象的顶点数据复制到 VBO(每个纹理/着色器一个 VBO),然后在单独的绘图调用中绘制每个 VBO。这似乎是一个好主意,直到我意识到它会弄乱绘制顺序 - 绘制调用不一定按照对象加载到 VBO 的顺序进行。我想过使用深度缓冲区对项目进行排序 - 每个要绘制的新对象的 Z 位置都会稍高一些。问题是,我应该增加多少才不会遇到任何问题?AFAIK,可能有两种问题 - 如果我把它设置得太大,那么我可以在一个帧中绘制的对象数量有限,如果我把它设置得太小,深度缓冲区的精度损失可能会导致重叠的图像以错误的顺序绘制。总结一下:
1)我的正投影的前后值应该是多少?0比1?-1比1?1比2?有关系吗?
2) 如果我使用 的 nextafter() 来增加 Z 位置,我会遇到什么样的麻烦?OpenGL 和深度缓冲区如何对次正常浮点数做出反应?如果我从 std::numeric_limits::min() 开始,并以 1 结束,还有什么我应该担心的吗?
我有一个金属视图,显示一些纹理四边形。纹理是从 PNG 加载的,因此会进行预乘。一些纹理具有透明像素。
当我启用混合并按正确的顺序绘制时,透明度起作用,您可以通过纹理的透明部分看到其他四边形下方的四边形。但是,我必须通过排序来计算正确的绘制顺序,这是昂贵的并且会大大减慢我的渲染速度。
当我尝试使用深度模板并以任何顺序绘制时,我可以使用 z 位置使顺序正确工作,但混合会停止工作。纹理的透明部分显示金属场景的背景颜色,而不是下面的四边形。
我究竟做错了什么?有没有办法让它工作并且有人可以提供一些示例代码?
我看到的另一个选择是尝试在 GPU 上进行排序,这很好,因为 GPU 帧时间明显小于 CPU 帧时间。但是,我也不确定如何做到这一点。
任何帮助将不胜感激。:)
我正在尝试在AR SceneKit演示的后处理步骤中进行深度测试。为此,我需要渲染器ARSCNView的深度图。使用SCNTechnique似乎无法获得它。
尝试将DRAW_SCENE传递的深度用作SCNTechnique的DRAW_QUAD传递的输入时,我一直保持空白(充满1.0-s)深度缓冲区。我遵循了SCNTechnique上的指南,并命名了深度目标。这是SCNTechnique实施中的错误,还是我在配置中缺少某些内容?
颜色缓冲区已正确链接,并且https://github.com/lachlanhurst/SCNTechniqueTest/tree/pixelate中的示例适用。
这是技术列表:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>passes</key>
<dict>
<key>pixelate_scene</key>
<dict>
<key>draw</key>
<string>DRAW_SCENE</string>
<key>inputs</key>
<dict/>
<key>outputs</key>
<dict>
<key>color</key>
<string>color_scene</string>
<key>depth</key>
<string>depth_scene</string>
</dict>
<key>colorStates</key>
<dict>
<key>clear</key>
<true/>
<key>clearColor</key>
<string>sceneBackground</string>
</dict>
</dict>
<key>resample_pixelation</key>
<dict>
<key>draw</key>
<string>DRAW_QUAD</string>
<key>program</key>
<string>doesntexist</string>
<key>metalVertexShader</key>
<string>pixelate_pass_through_vertex</string>
<key>metalFragmentShader</key>
<string>pixelate_pass_through_fragment</string>
<key>inputs</key>
<dict>
<key>colorSampler</key>
<string>color_scene</string>
<key>depthSampler</key>
<string>depth_scene</string>
</dict>
<key>outputs</key>
<dict>
<key>color</key>
<string>COLOR</string>
</dict>
</dict>
</dict>
<key>sequence</key>
<array>
<string>pixelate_scene</string>
<string>resample_pixelation</string>
</array>
<key>targets</key>
<dict>
<key>color_scene</key>
<dict>
<key>type</key> …Run Code Online (Sandbox Code Playgroud) 保存深度颜色模式纹理渲染的最简单方法是什么。可以在我的相机上不使用替换着色器的情况下完成此操作吗?
看起来大部分工作只需在具有渲染目标的相机上将颜色模式设置为深度即可完成。在材质上预览它,看起来很完美。我觉得保存它应该是微不足道的,但是,话又说回来,我对渲染缓冲区的了解还不够。
我知道您可以创建一个 Texture2D 并使用 ReadPixels 复制具有标准 rgba 颜色的活动渲染纹理,但是,我在计算如何仅使用深度来执行此操作时遇到问题。
如果我正确理解深度纹理,它们是 32 位单通道吗?但是,ReadPixel 仅适用于 RGBA32、ARGB32 和 RGB24 纹理格式。当我使用 ReadPixel 将其保存为 png 时,我似乎得到了一个灰色图像
color-depth texture2d unity-game-engine depth-buffer depth-testing
我不知道如何从带有后置 ToF 深度传感器的小米红米 Note 8 Pro 获取原始深度数据。
我试过了:
我正在使用 pyBullet,它是Bullet3物理引擎的Python包装器,我需要从虚拟相机创建点云。
该引擎使用基本的 OpenGL 渲染器,我能够从 OpenGL 深度缓冲区获取值
img = p.getCameraImage(imgW, imgH, renderer=p.ER_BULLET_HARDWARE_OPENGL)
rgbBuffer = img[2]
depthBuffer = img[3]
Run Code Online (Sandbox Code Playgroud)
现在我有带有深度值的宽度*高度数组。我如何从中获取世界坐标?我尝试用点(宽度、高度、深度缓冲区(宽度、高度))保存 .ply 点云,但这不会创建看起来像场景上的对象的点云。
我还尝试用近远平面校正深度:
depthImg = float(depthBuffer[h, w])
far = 1000.
near = 0.01
depth = far * near / (far - (far - near) * depthImg)
Run Code Online (Sandbox Code Playgroud)
但结果也是一些奇怪的点云。如何从深度缓冲区的数据创建真实的点云?有可能吗?
我在 C++ 中做了类似的事情,但是我使用了 glm::unproject
for (size_t i = 0; i < height; i = i = i+density) {
for (size_t j = 0; j < width; j = j = j+density) {
glm::vec3 win(i, …Run Code Online (Sandbox Code Playgroud)