几何着色器在线条之间产生间隙 [英] Geometry shader producing gaps between lines

查看:91
本文介绍了几何着色器在线条之间产生间隙的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我写了一个几何着色器来计算网格和平面的相交轮廓,但是在相交点有时两条线之间有1个像素宽的间隙.

I wrote a geometry shader to compute the intersection contour of a mesh and a plane, but at the intersection points there are sometimes 1 pixel wide gaps between two lines.

着色器首先计算三角形顶点到平面的符号距离.然后,它检查两个距离是否具有不同的符号,以确定是否与边相交.如果是这样,它将在相交处发出一个顶点,该顶点被计算为边缘点之间的加权平均值.

The shader first computes the signed distances of the triangle vertices to the plane. It then checks if two distances have a different sign to determine if there is an intersection with an edge. If so, it emits a vertex at the intersection, which is computed as the weighted average between the edge points.

#version 330
layout(triangles) in;
layout(line_strip, max_vertices = 3) out;

out vec3 vertexPosition;

uniform vec3 planePos;
uniform vec3 planeNormal;
uniform mat4 mvpMatrix;
uniform vec2 screenSize;

void intersection(in vec4 a, in float distA, in vec4 b, in float distB)
{
  if (sign(distA) * sign(distB) <= 0.0f && !(sign(distA) == 0 && sign(distB) == 0))
  {
    float fa = abs(distA);
    float fb = abs(distB);
    float fab = fa + fb;
    vec4 ptIntersection;
    // Don't divide by zero.
    if (fab < 0.001)
      ptIntersection = (a + b) * 0.5;
    else
      ptIntersection = (fa * b + fb * a) / fab;
    gl_Position = mvpMatrix * ptIntersection;
    vertexPosition = gl_Position.xyw;
    EmitVertex();
  }
}

void main()
{
  vec4 a = gl_in[0].gl_Position;
  vec4 b = gl_in[1].gl_Position;
  vec4 c = gl_in[2].gl_Position;

  float distA = dot(a.xyz - planePos, planeNormal);
  float distB = dot(b.xyz - planePos, planeNormal);
  float distC = dot(c.xyz - planePos, planeNormal);

  intersection(a, distA, b, distB);
  intersection(b, distB, c, distC);
  intersection(c, distC, a, distA);
}

我知道这很便宜,因为我忽略了所有三个点都在飞机上的特殊情况. !(sign(distA) == 0 && sign(distB) == 0)确保如果在平面上有两个点,则不会为该边缘发射任何顶点.因此,如果所有三个都躺在飞机上,将没有输出.但是我想那不一定是一件坏事.我喜欢的是没有疯狂的分支,并且如果可能的话,我希望保持这种状态.

I know it's kind of cheap, as I've ignored the special case where all three points lie on the plane. The !(sign(distA) == 0 && sign(distB) == 0) makes sure that if two points lie on the plane, no vertex will be emitted for that edge. So if all three lie on the plane, there will be no output. But I guess that's not necessarily a bad thing. What I like about it is that there is no crazy branching, and I'd like to keep it that way if possible.

所以我想知道:为什么我会看到这些差距?假设有两个三角形(a,b,c)和(c,b,d). a和b在平面上方,c和d在平面下方.对于第一个三角形,着色器生成与(b,c)的交点,对于第二个三角形,与(c,b)的交点.假设两个浮点数的加法运算是可交换的,则intersection函数与输入对称,因此结果应相同.为什么我仍然看到这些差距?

So I'm wondering: Why do I see these gaps? Let's say there are two triangles (a,b,c) and (c,b,d). a and b are above the plane, c and d below. For the first triangle, the shader generates the intersection with (b,c), for the second the intersection with (c,b). Assuming that the addition of two floats is commutative, then the intersection function is symmetrical wrt the inputs, so the results should be the same. Why do I still see these gaps?

推荐答案

答案在于OpenGL规范给出的Bresenham线光栅化算法的规范.引用OpenGL 3.3 规范,第3.5.1节:

The answer lies in the specification of the Bresenham line rasterization algorithm that the OpenGL specification gives. Quote from the OpenGL 3.3 Spec, section 3.5.1:

栅格化从pa开始并在pb处终止的线段将产生片段f,其片段从pa开始并在pb处终止与Rf相交,除非pb包含在Rf中(以片段为中心的钻石区域).

Rasterizing the line segment starting at pa and ending at pb produces those fragments f for which the segment starting at pa and ending on pb intersects Rf, except if pb is contained in Rf [diamond region centered on the fragment].

如果不幸的是,两条相邻的线不幸沿相反的方向(即在同一点结束)行进,并且该端点包含在像素中心周围的菱形中,则根本不会对端点进行栅格化.因此,您将看到明显的差距.

With the effect that the endpoint is not rasterized at all if two neighboring lines of yours unfortunately run in opposite directions (i.e. end in the same point) and that endpoint is contained in said diamond around the pixel center. Thus you will see a noticeable gap.

由于您已经在使用几何着色器,因此您当然可以(通过一些额外的计算)发出三角形以形成真实的"宽线.

As you are already using geometry shaders, you can of course (with a bit of additional calculation) emit triangles to make a "true" wide line.

这篇关于几何着色器在线条之间产生间隙的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆