opengl 与世界空间大小对应的gl_PointSize

hfwmuf9z  于 2022-11-04  发布在  其他
关注(0)|答案(1)|浏览(147)

如果要渲染一个冒名顶替的几何体(比如a sphere),那么标准做法是使用两个三角形绘制它(比如通过传递一个顶点并使用几何体着色器生成一个三角形条带)。
这很好,因为它允许广告牌的范围设置得相当简单:您可以直接计算实际的世界空间位置。
几何着色器可以交替输出点图元,我看不出它们不应该输出点图元的原因。唯一的问题是找到某种方法来缩放gl_PointSize,以便获得这种效果。
我能找到的唯一先例是this question(我不确定它的答案是否正确)和this question(没有答案)。
值得注意的是,用距离来正确地缩放点是相当简单的(通过gl_PointSize = constant/length(gl_Position),但这是不可控的;你不能说例如:我希望该点看起来像是两个世界单位的跨度。
所以:有人知道怎么做吗?

yqlxgs2m

yqlxgs2m1#

一个直接的想法是将粒子顶部和底部的一个点转换到屏幕空间,并找到距离。这可以很好地抵消,而且只使用y坐标非常简单。
广告牌是屏幕对齐的,视图矩阵通常不会缩放,因此世界空间中的粒子大小与眼睛空间中的粒子大小相同,这就只剩下投影到达NDC,除以w,然后按视口大小缩放。
一个典型的投影矩阵P可能看起来像这样...

[ +1.2990 +0.0000 +0.0000 +0.0000 ]
[ +0.0000 +1.7321 +0.0000 +0.0000 ]
[ +0.0000 +0.0000 -1.0002 -0.0020 ]
[ +0.0000 +0.0000 -1.0000 +0.0000 ]

y_eye(眼空间中的y坐标)开始,图像空间坐标y_image以像素为单位获得...

插入广告牌上方/下方的半径并减去取消...

或者,在文本中,pixelSize = vpHeight * P[1][1] * radius / w_clip
对于透视投影,P[1][1] = 1 / tan(fov_y / 2). w_clipgl_Position.w,也是-z_eye(来自透视矩阵中的-1)。为了保证点覆盖所需的每个像素,这可能需要一个额外的小常量。
边注:广告牌上的球体在屏幕中间看起来不错。如果你有一个大视野的透视投影,一个真实的球体在接近屏幕边缘时应该会扭曲。你可以隐式地对广告牌上的每个像素进行虚拟球体的光线投射,以获得正确的结果,但广告牌的边界需要相应地调整。快速谷歌结果:第一个
[* 编辑 *]
好吧,既然我费心测试了这个,我也会把我的着色器扔在这里...
顶点:


# version 150

in vec4 osVert;

uniform mat4 projectionMat;
uniform mat4 modelviewMat;
uniform vec2 viewportSize;

flat out vec2 centre;
flat out float radiusPixels;

const float radius = 1.0;

void main()
{
    gl_Position = projectionMat * modelviewMat * osVert;
    centre = (0.5 * gl_Position.xy/gl_Position.w + 0.5) * viewportSize;
    gl_PointSize = viewportSize.y * projectionMat[1][5] * radius / gl_Position.w;
    radiusPixels = gl_PointSize / 2.0;
}

片段:


# version 150

flat in vec2 centre;
flat in float radiusPixels;

out vec4 fragColour;

void main()
{
    vec2 coord = (gl_FragCoord.xy - centre) / radiusPixels;
    float l = length(coord);
    if (l > 1.0)
        discard;
    vec3 pos = vec3(coord, sqrt(1.0-l*l));
    fragColour = vec4(vec3(pos.z), 1.0);
}

(Note右下角的可见间隙如上所述不正确)

相关问题