抱歉,它还没有被任何东西取代。我想到的第一个模拟它的想法是几何着色器。您向几何着色器提供一条线,计算其屏幕空间长度,并基于此在其起始顶点和结束顶点之间生成可变数量的子线。
EDIT:也许您还可以使用带有 alpha(或红色)通道的 1D 纹理,将图案编码为 0.0(无线)或 1.0(线),然后让线纹理坐标从 0 到 1,并在片段 Chader 中创建一个简单的 alpha 测试,丢弃 alpha 低于某个阈值的片段。您可以方便几何着色器生成线条 texCoords,否则每条线条都需要不同的顶点。通过这种方式,您还可以使 texCoord 依赖于线条的屏幕空间长度。
如果你绘制三角形(使用多边形模式),整个事情就会变得更加困难GL_LINE
)。然后,您必须在几何着色器中自己进行三角形线转换,放入三角形并输出直线(这也可能是将来弃用多边形模式的一个原因,如果还没有的话)。
EDIT:尽管我相信这个问题已经被放弃,但我已经为第二种方法制作了一个简单的着色器三元组。这只是一个最小的解决方案,您可以随意添加自定义功能。我没有测试过它,因为我缺乏必要的硬件,但你应该明白这一点:
uniform mat4 modelViewProj;
layout(location=0) in vec4 vertex;
void main()
{
gl_Position = modelViewProj * vertex;
}
顶点着色器是一个简单的传递。
layout(lines) in;
layout(line_strip, max_vertices=2) out;
uniform vec2 screenSize;
uniform float patternSize;
noperspective out float texCoord;
void main()
{
vec2 winPos0 = screenSize.xy * gl_in[0].gl_Position.xy / gl_in[0].gl_Position.w;
vec2 winPos1 = screenSize.xy * gl_in[1].gl_Position.xy / gl_in[1].gl_Position.w;
gl_Position = gl_in[0].gl_Position;
texCoord = 0.0;
EmitVertex();
gl_Position = gl_in[1].gl_Position;
texCoord = 0.5 * length(winPos1-winPos0) / patternSize;
EmitVertex();
}
在几何着色器中,我们取一条线并计算其屏幕空间长度(以像素为单位)。然后我们通过点画图案纹理的大小来划分它,这将是factor*16
当模拟调用时glLineStipple(factor, pattern)
。这被视为第二条线端点的一维纹理坐标。
请注意,该纹理坐标必须进行线性插值(noperspective
插值说明符)。通常的透视校正插值会导致点画图案“挤在一起”在线的较远部分,而我们明确地使用屏幕空间值。
uniform sampler1D pattern;
uniform vec4 lineColor;
noperspective in float texCoord;
layout(location=0) out vec4 color;
void main()
{
if(texture(pattern, texCoord).r < 0.5)
discard;
color = lineColor;
}
片段着色器现在仅使用图案纹理中的值执行简单的 Alpha 测试,其中 1 表示线条,0 表示无线条。因此,要模拟固定功能点画,您将拥有 16 像素 1 分量 1D 纹理,而不是 16 位图案。不要忘记将图案的环绕模式设置为GL_REPEAT
,关于过滤模式我不太确定,但我想GL_NEAREST
将是一个好主意。
但如前所述,如果你想使用渲染三角形glPolygonMode
,这样就行不通了。相反,您必须调整几何着色器以接受三角形并为每个三角形生成 3 条线。
EDIT:事实上,OpenGL 3 对着色器中整数运算的直接支持使我们能够完全放弃整个 1D 纹理方法,并直接使用实际的位模式进行工作。因此,几何着色器稍微改变以输出实际的屏幕尺寸图案坐标,而不进行标准化:
texCoord = 0.5 * length(winPos1-winPos0);
在片段着色器中,我们只需将位模式作为无符号整数(尽管 32 位与glLineStipple
的 16 位值)和图案的拉伸因子,只需将纹理坐标(好吧,实际上不再有纹理,但没关系)模 32 来获取它在图案上的位置(那些明确的uint
s 很烦人,但是我的 GLSL 编译器说之间存在隐式转换int
and uint
是邪恶的):
uniform uint pattern;
uniform float factor;
...
uint bit = uint(round(linePos/factor)) & 31U;
if((pattern & (1U<<bit)) == 0U)
discard;