让我们先看一张图片:
图像中的模型是通过纹理映射创建的。我想在屏幕上点击鼠标,然后我想在模型的表面上放置一个固定点。而且,随着模型的旋转,固定点仍然在模型的表面上。
我的问题是:
我的想法如下:
这是我的想法。但似乎它不起作用!任何人都可以给我一些建议。谢谢!
答案 0 :(得分:0)
图像中的模型是通过纹理映射创建的。
不,不是。首先,根本没有模型。你有一个体素的3D数据集,然后你有一个体积光栅化器,通过数据集“射击”光线,整合它们,并为每个光线产生颜色和不透明度值。
此过程不是(!!!)纹理映射。纹理映射是指绘制“实体”基元时,每个片段(片段最终成为像素)确定纹理数据集中的单个位置并对其进行采样。 但是你可以在那里使用体积比较器来执行整个光线集成,从整个数据集中有效地将许多体素采样为单个像素。这是一种完全不同的创建颜色不透明度值的方法。
我的问题是:
- 如何将固定点放在模型的表面上?
你不能,因为那里的数据集没有“固定”的表面点。您必须定义某些分段操作,该操作决定沿着光线的哪个位置构成“这是表面”。最简单的方法是使用阈值截止函数。
- 如何获得固定点的坐标(x,y,z)?
您最好的选择是修改音量光线投射代码,将其从积分器更改为分段器。假设您要使用阈值方法。
您的典型体积光栅化器的工作原理如下(通常在着色器中实现):
vec4 output;
for(vec3 pos = start
; length(pos - start) <= length(end - start)
; pos += voxel_grid_increment ){
vec4 t = texture3D(voxeldata, pos);
/* integrate t into output */
}
积分步骤将纹理体素t的输入颜色和不透明度合并为输出颜色+不透明度。有几种方法可以做到这一点。
你可以将它改成一个着色器,它只是在给定的截止阈值处停止该循环并发出该体素的位置:
vec3 output;
for(vec3 pos = start
; length(pos - start) <= length(end - start)
; pos += voxel_grid_increment ){
float t = texture3D(voxeldata, pos).r;
if( t > threshold ){
output = pos;
break;
}
}
其结果将是在其像素RGB值中编码所确定的体素位置的图片。使用每通道16位纹理格式(或半精度浮点数的单精度),您可以获得足够的分辨率,以满足典型GPU在3D纹理中可以处理的限制。
您希望使用FBO在屏幕外执行此操作。
另一种可行的方法是采用常规体素raycaster并在阈值位置修改特定片段的深度值输出。这种方法的缺点是,深度输出修改会破坏性能,因此如果帧速率很重要,您将不希望这样做。这种方法的好处是,你实际上可以在深度缓冲区上使用glReadPixels
并在你的moust指针的位置使用gluUnProject
深度值。
我的想法如下:
使用gluUnproject函数在我有鼠标时得到两个点 点击屏幕。一点是在近夹片平面上 另一个是远方的。将这两点连接起来形成一个 线。 迭代第2步行的点并使用glReadPixels来获取 迭代点的像素值。如果值跳过 零到非零或从非零跳到零(像素值为 背景为零),找到表面点。
那不行。出于简单的原因,glReadPixels
看到的与您看到的完全相同。您无法“选择”glReadPixels
读取像素的深度,因为图片中没有深度。 glReadPixels
只看到你看到的内容:窗口中显示的平面图像。您将不得不迭代体素数据,但您不能在事后进行此操作。您必须实现或修改卷raterizer以提取所需的信息。
答案 1 :(得分:-1)
我不打算在这里写下你需要的全部实现。另外,你可以在网上搜索关于这个主题的find quite alot信息。但是你要找的是{{3} .Nvidia还提出了一种名为"Decals"的技术。简而言之,你绘制一个平面(或封闭的体积)几何体来将贴花纹理投射到它上面。实际过程有点复杂,你可以看到例子。