在片段着色器中绘制别名像素完美线?
Posted
技术标签:
【中文标题】在片段着色器中绘制别名像素完美线?【英文标题】:Drawing aliased pixel-perfect lines in fragment shader? 【发布时间】:2019-10-23 09:39:22 【问题描述】:我正在尝试使用片段着色器在 OpenGL 中绘制像素完美的线条。我有以下从this question 获得的片段着色器。然而,结果是 2 像素而不是 1 像素。
#version 330
layout(location=0) out vec4 frag_colour;
in vec4 color;
uniform vec2 positionA;
uniform vec2 positionB;
uniform int thickness;
float lineSegment(vec2 p, vec2 a, vec2 b, float thickness)
vec2 pa = p - a;
vec2 ba = b - a;
float h = clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0 );
float k = length(pa - ba*h);
return smoothstep(0.0, thickness, k);
void main()
vec2 uv = gl_FragCoord.xy;
frag_colour = mix(color,vec4(0),lineSegment(uv,positionA,positionB,thickness));
据我了解,这是因为无论“线”在哪里,从技术上讲,两侧的像素距离相同,所以如果我尝试移除任何类型的抗锯齿,它们都“在线” " 所以我的 1 像素宽的线最终变成了 2 像素。
您可以看到黄色水平线是 2 像素宽(将其与文本中的各个像素进行比较)。
我在网上到处尝试了一些其他的片段代码,它们都存在同样的问题。
如何在 GLSL 中绘制像素完美的锯齿线(非抗锯齿线)?
编辑 1
通过0.5f
调整位置和粗细后,移动到像素的中心,对角线在每一种“台阶”上都有抗锯齿。
对角线:
【问题讨论】:
thickness
就像是一条线周围的半径。如果您指定 1 个像素,您将获得上方 1 个像素和下方 1 个像素,即总共 2 个像素。如果您使用 0.5px 半径,请确保在像素中心指定端点,以避免数值不稳定。
谢谢@Nico,为水平/垂直线做了这件事。但是以一定角度延伸的线添加了抗锯齿功能。
然后将smoothstep
替换为return k <= thickness ? 0 : 1
。
就是这样@NicoSchertler。在有人解释之后总是很明显。如果您将其放入答案中,我会接受。
【参考方案1】:
也许这会有所帮助(在 shadertoy 中测试):
bool lineSegment(vec2 p, vec2 a, vec2 b, float thickness)
vec2 pa = p - a;
vec2 ba = b - a;
float len = length(ba);
vec2 dir = ba / len;
float t = dot(pa, dir);
vec2 n = vec2(-dir.y, dir.x);
float factor = max(abs(n.x), abs(n.y));
float distThreshold = (thickness - 1.0 + factor)*0.5;
float proj = dot(n, pa);
return (t > 0.0) && (t < len) && (proj <= distThreshold) && (proj > -distThreshold);
void mainImage(out vec4 fragColor, in vec2 fragCoord)
vec2 positionA = iResolution.xy * 0.5;
vec2 positionB = iMouse.xy;
float thickness = 1.0;
fragColor = mix(vec4(0), vec4(1), float(lineSegment(fragCoord,positionA,positionB,thickness)));
以防万一,here's math.stackexchange 上的相关问题。
【讨论】:
以上是关于在片段着色器中绘制别名像素完美线?的主要内容,如果未能解决你的问题,请参考以下文章