点画模式的片段着色器

时间:2017-04-13 12:27:23

标签: opengl fragment-shader

我正在尝试使用着色器绘制点画图案,就像在glStipple中一样。但它似乎没有按预期工作。

我们的想法是将像素坐标与点画蒙版进行比较,如果像素坐标模板掩码大小为0,则丢弃片段。

然而,发生了两件奇怪的事情,这表明这种方法存在一些我不知道的缺陷。第一个是得到的点画图案与面具不匹配。 8x8掩模中的单个对角线导致在绘制的形状中看起来是间隔1个像素的对角线。第二个是对1而不是0进行测试不会给出类似(但移位)的模式。

顶点着色器如下所示:

static const char *vertexShaderSource =
"attribute highp vec4 posAttr;\n"
"attribute highp vec4 colAttr;\n"
"varying lowp vec4 col;\n"
"varying highp vec2 coord;\n"
"uniform highp mat4 matrix;\n"
"void main() {\n"
"   col = colAttr;\n"
"   gl_Position = matrix * posAttr;\n"
"   coord = gl_Position.xy;\n"
"}\n";

和片段着色器:

static const char *fragmentShaderSource =
"varying lowp vec4 col;\n"
"varying highp vec2 coord;\n"
"uniform int stipple[64];\n"
"uniform int width;\n"
"uniform int height;\n"
"void main() {\n"
"   if (stipple[abs(mod(coord.x * width,8)) + abs(mod(coord.y * height,8)) * 8] == 1)\n"
"   {\n"
"       discard;\n"
"   }\n"
"   gl_FragColor = col;\n"
"}\n";

其中width和height是视口的w / h,点画是例如。

GLint stipple[64] = {
    0, 0, 0, 0, 0, 0, 0, 1,
    0, 0, 0, 0, 0, 0, 1, 0,
    0, 0, 0, 0, 0, 1, 0, 0,
    0, 0, 0, 0, 1, 0, 0, 0,
    0, 0, 0, 1, 0, 0, 0, 0,
    0, 0, 1, 0, 0, 0, 0, 0,
    0, 1, 0, 0, 0, 0, 0, 0,
    1, 0, 0, 0, 0, 0, 0, 0
};

任何想法都表示赞赏,谢谢。

1 个答案:

答案 0 :(得分:3)

您可以使用gl_FragCoord。它包含像素的中心坐标。因此,对于800x600的分辨率,则gl_FragCoord将在vec2(0.5, 0.5)vec2(799.5, 599.5)的范围内。因此,不需要乘以分辨率,因为我们已经基本上有窗口坐标。

由于gl_FragCoord不会产生负数,因此您可以删除abs()

总而言之,经过少量修改后,片段着色器最终看起来像这样:

varying vec4 color;

uniform int stipple[64];

void main()
{
    ivec2 coord = ivec2(gl_FragCoord.xy - 0.5);

    if (stipple[int(mod(coord.x, 8) + mod(coord.y, 8) * 8)] == 0)
       discard;

    gl_FragColor = color;
}