我正在尝试使用着色器绘制点画图案,就像在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
};
任何想法都表示赞赏,谢谢。
答案 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;
}