- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我最近将一个使用 D3DXIntersect 查找光线/网格交点的 DirectX 9 应用程序转换为 DirectX 11。由于 D3DXIntersect 在 DX11 中不可用,我编写了自己的代码来查找交点,它只是循环遍历中的所有三角形网格并测试它们,跟踪最接近原点的命中。这是在 CPU 端完成的,可以很好地通过 GUI 进行拾取,但是我有应用程序的另一部分,它根据几个不同的视点从现有的网格创建一个新的网格,我需要检查每个三角形的视线在网格中多次。这变得很慢。
使用 DX11 计算着色器来执行此操作是否有意义(即在 CPU 上执行此操作是否会显着加快速度)?我在互联网上搜索但找不到现有示例。
假设答案是肯定的,这是我正在考虑的方法:
我希望我可以访问 DirectX 中的 CUDA Thrust 之类的东西,因为我认为编写这种减少的代码会很痛苦。这就是我问的原因,所以我不会白做一堆工作!
最佳答案
这是完全可行的,这里有一些 HLSL 代码可以执行此操作(并且还可以处理您击中 2 个具有相同距离的三角形的情况)。
我假设您知道如何创建资源(结构化缓冲区)并将它们绑定(bind)到计算管道。
此外,我会认为您的几何图形已编入索引。
第一步是收集通过测试的三角形。我们将使用追加缓冲区来仅推送通过测试的元素,而不是使用“命中”标志。
首先创建 2 个结构化缓冲区(位置和三角形索引),然后将您的模型数据复制到其中。
然后创建一个带有可追加无序 View 的结构化缓冲区。
要执行命中检测,您可以使用以下计算代码:
struct rayHit
{
uint triangleID;
float distanceToTriangle;
};
cbuffer cbRaySettings : register(b0)
{
float3 rayFrom;
float3 rayDir;
uint TriangleCount;
};
StructuredBuffer<float3> positionBuffer : register(t0);
StructuredBuffer<uint3> indexBuffer : register(t1);
AppendStructuredBuffer<rayHit> appendRayHitBuffer : register(u0);
void TestTriangle(float3 p1, float3 p2, float3 p3, out bool hit, out float d)
{
//Perform ray/triangle intersection
hit = false;
d = 0.0f;
}
[numthreads(64,1,1)]
void CS_RayAppend(uint3 tid : SV_DispatchThreadID)
{
if (tid.x >= TriangleCount)
return;
uint3 indices = indexBuffer[tid.x];
float3 p1 = positionBuffer[indices.x];
float3 p2 = positionBuffer[indices.y];
float3 p3 = positionBuffer[indices.z];
bool hit;
float d;
TestTriangle(p1,p2,p3,hit, d);
if (hit)
{
rayHit hitData;
hitData.triangleID = tid.x;
hitData.distanceToTriangle = d;
appendRayHitBuffer.Append(hitData);
}
}
请注意,您需要为 appendRayHitBuffer 提供足够的大小(最坏的情况是三角形计数,例如:每个三角形都被光线击中)。
完成后,缓冲区的开始部分包含命中数据,无序 View 计算通过测试的三角形数。
然后您需要创建一个参数缓冲区和一个小的字节地址缓冲区(大小为 16,因为我认为运行时不允许 12)
你还需要一个小的结构化缓冲区(一个元素就够了),用来存储最小距离
使用CopyStructureCount将 UnorderedView 计数器传递到这些缓冲区(请注意,Argument 缓冲区的第二个和第三个元素需要都设置为 1,因为它们将是使用分派(dispatch)的参数)。
使用 UINT_MAXVALUE 清除小型 StructuredBuffer 缓冲区,并使用参数缓冲区 DispatchIndirect
我假设你不会有很多命中,所以对于下一部分,numthreads 将设置为 1,1,1(如果你想使用更大的组,你将需要运行另一个计算着色器来构建参数缓冲区) .
然后求最小距离:
StructuredBuffer<rayHit> rayHitbuffer : register(t0);
ByteAddressBuffer rayHitCount : register(t1);
RWStructuredBuffer<uint> rwMinBuffer : register(u0);
[numthreads(1,1,1)]
void CS_CalcMin(uint3 tid : SV_DispatchThreadID)
{
uint count = rayHitCount.Load(0);
if (tid.x >= count)
return;
rayHit hit = rayHitbuffer[tid.x];
uint dummy;
InterlockedMin(rwMinBuffer[0],asuint(hit.distanceToTriangle), dummy);
}
由于我们预计命中距离将大于零,因此我们可以在这种情况下使用 asuint 和 InterlockedMin。此外,由于我们使用 DispatchIndirect,这部分现在仅应用于之前通过测试的元素。
现在您的单个元素缓冲区包含最小距离,但不包含索引(或索引)。
最后,我们需要最终提取出命中距离最小的三角形索引。
您再次需要一个带有 UnorderedView 的新 StructuredBuffer 来存储最小索引。
使用与之前相同的调度参数(间接),并执行以下操作:
ByteAddressBuffer rayHitCount : register(t1);
StructuredBuffer<uint> MinDistanceBuffer : register(t2);
AppendStructuredBuffer<uint> appendMinHitIndexBuffer : register(u0);
[numthreads(1,1,1)]
void CS_AppendMin(uint3 tid : SV_DispatchThreadID)
{
uint count = rayHitCount.Load(0);
if (tid.x >= count)
return;
rayHit hit = rayHitbuffer[tid.x];
uint minDist = MinDistanceBuffer[0];
uint d = asuint(hit.distanceToTriangle);
if (d == minDist)
{
appendMinHitIndexBuffer.Append(hit.triangleID);
}
}
现在 appendMinHitIndexBuffer 包含最接近的三角形索引(如果您有这种情况,则可以包含多个),您可以使用 Staging 资源将其复制回来并映射您的资源以供读取。
关于directx-11 - 用于光线/网格相交的 DirectX 11 计算着色器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40184304/
我有一个标记的个体列表(Mark 列),这些个体在河流(LocStart 和 LocEnd)范围内的不同年份(Year 列)被捕获。在河上的位置以米为单位。 我想知道一个被标记的个体是否在不同年份之间
我目前正在开发一个事件管理系统,其中数据库存储时隙,如下所示: SlotId | DateTime | Duration -------+-------------------
给定同一个圆的两个圆段:A=[a1, a2] 和 B=[b1, b2],其中: a1、a2、b1、b2 的值介于 -inf 和 +inf 之间 a1 overlap A=[ -45°, 45
试图让两个数据集相交,但我做不到。例如,在我下面的代码中,相交 mySet 和 mySet2 应该产生“1”,因为它们在它们的集合中都有一个值“1”。 var mySet = new Set(); v
给定同一个圆的两个圆段:A=[a1, a2] 和 B=[b1, b2],其中: a1、a2、b1、b2 的值介于 -inf 和 +inf 之间 a1 overlap A=[ -45°, 45
我有两个要相交的集合,并对匹配元素执行求和运算。 例如集合是(在伪代码中): col1 = { {"A", 5}, {"B", 3}, {"C", 2} } col2 = { {"B", 1}, {"
我有一个使用 -setFrameRotation 旋转的 NSView。 (这是必要的,因为 View 响应鼠标事件,如果您仅使用旋转的 NSAffineTransform 绘制 View ,则不会获
我在网上找到了这段代码,显然它对其他人有效,但对我无效?我不知道哪里错了。我做了一个简单的例子,并将我的 Range1 和 Range 2 设为 excel 中的某些单元格, 另外,我想知道是否有办法
确定直线是否与矩形相交的最有效方法是什么? 我正在寻找类似的东西: CGPoint startLine = CGPointMake(5.0f,5.0f); CGPoint endLine = CGPo
QPolygonF有与其他 QPolygonF 并集、相交和相减的方法,但我需要与 QLineF 执行相交测试。 API 中似乎缺少此功能。 我想我可以做这样的事情: if (polygon .con
所以,我尝试使用矩形在游戏中对墙壁进行碰撞,我决定尝试使用 ArrayList 来存储每面墙的矩形,然后我将整个 field 设为一面墙,并且所有我想做的是删除三堵墙,所以我正在执行 shapeLis
鉴于这两个表/集合具有不同的项目组, 我如何找到 set1 中的哪些组跨越 set2 中的多个组? 如何找到 set1 中的组不能被 set2 中的单个组覆盖? 例如对于下表,A (1,2,5) 是唯
我在 Hive 中有两个字符串数组,例如 {'value1','value2','value3'} {'value1', 'value2'} 我想合并没有重复的数组,结果: {'value1','va
谁能给我 tsql 来查找包含起始日期和截止日期的日期。 select * from empc where DateFrom >= p_todate AND DateTo = p_fromdate 关
我正在尝试从分桶列中获取子集,然后获取交集。 这将从原始表中选择其他列。 我也对系列过滤持开放态度。 下面的代码报告 col1 不存在 - 不确定这是正确的方法。 WITH ranges AS (
SELECT friend_id FROM friendships WHERE user_id = 1; Returns: +-----------+ | friend_id | +---------
似乎无法在任何地方找到这个问题的答案。 我的游戏在用户触摸屏幕时开始,手指必须停留在一条路径内,如果它触摸/与边缘相交,那么我希望它运行 [self gameover] 方法。 边缘将是一个 UIIm
我有两个 RDD,一个非常大,另一个小得多。我想用小 RDD 的键在大 RDD 中找到所有唯一的元组。 大 RDD 太大,我必须避免完全洗牌 小型 RDD 也足够大,我无法广播它。我也许可以广播它的
所以我有两个函数的代码。第一个打印一个空的 20x20 板,第二个打印中间的一个字。现在我正在尝试编写一个函数来检查输入的单词是否会与同一字母的另一个单词(如填字游戏)相交。这是前两个函数的代码(此处
我正在一个网站上进行培训,该网站要求我制作一个程序,该程序将询问两个矩形的坐标并检查矩形是否相交。然后,当我发送程序时,网站会对其进行几次测试。它要求 A 矩形的 x 最小值、x 最大值、y 最小值和
我是一名优秀的程序员,十分优秀!