2011-05-16 257 views
18

glLineStipple已在最新的OpenGL API中弃用。 它取代了什么? 如果没有更换,我怎样才能得到类似的效果? (我当然不想使用兼容性配置文件...)glLineStipple在OpenGL 3.1中已弃用

+0

不是真的放弃,学习和玩opengl是一种爱好,而我其实很少花时间。但我很乐意投你的答案! – Vincent 2011-07-05 15:34:16

回答

22

对不起,它没有被任何东西取代。我脑海中模拟它的第一个想法是几何着色器。您使用一条线向几何着色器提供数据,计算其屏幕空间长度,并基于该数据着色器在其开始和结束顶点之间生成可变数量的子线。


编辑:也许你也可以使用一维纹理与α(或红色)信道的编码模式为0.0(无线)或1.0(线),然后使线纹理坐标从去0到1,并在片段chader中进行简单的阿尔法测试,丢弃alpha低于某个阈值的片段。您可以方便几何着色器生成线条texCoords,否则每条线都需要不同的顶点。这样你也可以使texCoord依赖于该行的屏幕空间长度。

如果绘制三角形(使用多边形模式GL_LINE),整个事情会变得更加困难。然后,您必须在几何着色器中自己进行三角形线转换,放入三角形并放出线条(如果尚未推出多边形模式,也可以这样做)。


编辑:虽然我相信这个问题abandomned,我做了一个简单的着色器三联供第二种方法。这只是一个最小的解决方案,请随时自行添加自定义功能。我没有测试它,因为我缺乏neccessary硬件,但你应该明白了吧:

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(); 
} 

在几何着色器中,我们取一条线并计算其像素的屏幕空间长度。然后,我们将此点划分为点画图纹理的大小,当模拟对glLineStipple(factor, pattern)的调用时,这将是factor*16。这被视为第二行结束点的一维纹理坐标。

请注意,此纹理坐标必须线性内插(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行。


编辑:事实上的OpenGL 3的直接用于整数运算着色器的支持,使我们彻底放弃这一整个1D纹理方法和工作直接的与实际的位模式。因此,几何形状着色器被稍微改变为放出来的实际屏幕大小图案坐标,而不归一化:

texCoord = 0.5 * length(winPos1-winPos0); 

在片段着色器我们然后只取一个位模式为无符号整数(尽管在对比32位并且只取纹理坐标(好吧,没有纹理了,但实际上却从来没有)模32以获得它在图案上的位置(这些明确的uints很烦人,但是,我的GLSL编译器说在intuint之间的隐式转换是邪恶的):

uniform uint pattern; 
uniform float factor; 

... 
uint bit = uint(round(linePos/factor)) & 31U; 
if((pattern & (1U<<bit)) == 0U) 
    discard; 
+0

大thx为您的重播!它的伟大和深入。 – 2012-03-14 22:56:57

+2

太棒了。但是在OpenGLES-2中没有几何着色器可以完成吗? – Bram 2012-04-30 22:28:44

+0

@Bram是的。我没有使用几何着色器来生成新的基元,只是基于其屏幕空间长度来计算直线的纹理坐标。您可以在没有GS的情况下执行此操作,但在这种情况下,您必须计算CPU上的texCoords。但是这意味着你必须重复顶点,因为每个顶点需要不同的texCoord,并且你不能依赖于屏幕空间大小(很好,你仍然可以计算它在CPU上的屏幕空间长度,但是每一帧?)。它不能在VS中完成,因为您只能看到一个顶点而不是整条线。 – 2012-04-30 22:49:52