我试图在曲面上得到一个段最近的点,并在这个位置上显示一个圆(在这种情况下是球体)。
实际上,我得到了正确的位置,但是我不能根据计算的数据得到一个均匀的球。

下面是我用来找到交点和绘制球体的相关代码。
float3 a = from;
float3 b = to;
float3 c = worldPosition;
float3 ab = b - a;
float t = dot(c - a, ab) / dot(ab, ab);
float3 point = a + saturate(t) * ab;
return length(point - worldPosition) - radius;发布于 2020-06-11 11:52:32
你的实际结果是正确的,因为你可以在一个片段着色器一次通过。它计算碎片的世界位置到线段的距离。每个片段的距离是不同的,所以拉伸的黑色椭球是正确的输出。
片段着色器只有正在处理的当前片段的本地信息。你不能再用那个做更多了。您的预期结果需要一些关于场景的全局知识,因为您正在搜索整个表面的最小距离。
在不考虑优化问题的情况下,朴素解路径应该包含片段到线距离的局部极小值的上下文计算。为了得到这样的上下文,您需要先计算距离字段,然后访问它,以便在单独的pass中找到局部最小值。
radius减法)。rgba浮点纹理,rgb是片段的世界位置,a是局部极小值和0的位置。有了关于距离函数的局部最小值的信息,您就可以在最后一次输出最小值附近的正确形状。伪码:
vec4 worldPos = tex2D(distance_texture, frag.x, frag.y);
if (worldPos.a > 0.5) //is minimum
return vec3(0,0,0);
else
{
//Sample the screen-space neighborhood in larger and larger circles
// until a fragment with distance.a == 1 is found
// or until all fragments are more than radius away (in world coords).
//Minimum world space distance of any sampled fragment.
float minDist = 0.0;
int iter = 1;
//Search for a local minimum until all fragments are more than radius away,
// since then even if a local minimum gets found it will no longer produce
// the black shading.
while (minDist < radius && minDist >= 0.0 && iter < Math.Max(screenWidth, screenHeight))
minDist = sampleNeighborhood(iter++, worldPos);
if (minDist < 0.0) //found a local minimum
return vec3(0,0,0);
else
return vec3(1,1,1); //or any other computed shading
//I am aware that the function call above checks central fragments several times.
//That should be of course optimized in production code.
}
float sampleNeighborhood(int neigh, vec4 worldPos)
{
float minDist = float.MaxValue;
for(int x = Math.max(0, frag.x - neigh); x <= Math.Min(screenWidth, frag.x + neigh; ++x)
for(int y = Math.max(0, frag.y - neigh); x <= Math.Min(screenHeight, frag.y + neigh; ++y)
{
float p = tex2D(distance_texture, x, y);
float d = distance(p.xyz, worldPos.xyz);
if (p.a > 0.5 && d <= radius)
//Return negative distance to indicate a local minimum was found.
return -1.0;
else
minDist = Math.min(minDist, d);
}
return minDist;
}在第二次测试中找到局部极小值要容易得多,因为您只需要对本地3x3邻域进行采样。
我希望这能帮助你达到预期的渲染效果!
https://computergraphics.stackexchange.com/questions/9935
复制相似问题