[英]Draw a simple dotted line or dashed line in OpenGL GLES20 android using fragment shader and GL_LINE_STRIP
[英]Is it possible to draw line thickness in a fragment shader?
考虑到我用 GL_LINES 绘制线条,我是否可以在片段着色器中添加线条粗细? 我看到的大多数示例似乎只访问片段着色器中基元内的纹素,而线粗度着色器需要写入线基元外的纹素以获得厚度。 但是,如果可能的话,一个非常小的、基本的示例会很棒。
片段着色器可以实现很多功能。 看看有些人在做什么。 我自己离那个水平很远,但这段代码可以给你一个想法:
#define resolution vec2(500.0, 500.0)
#define Thickness 0.003
float drawLine(vec2 p1, vec2 p2) {
vec2 uv = gl_FragCoord.xy / resolution.xy;
float a = abs(distance(p1, uv));
float b = abs(distance(p2, uv));
float c = abs(distance(p1, p2));
if ( a >= c || b >= c ) return 0.0;
float p = (a + b + c) * 0.5;
// median to (p1, p2) vector
float h = 2 / c * sqrt( p * ( p - a) * ( p - b) * ( p - c));
return mix(1.0, 0.0, smoothstep(0.5 * Thickness, 1.5 * Thickness, h));
}
void main()
{
gl_FragColor = vec4(
max(
max(
drawLine(vec2(0.1, 0.1), vec2(0.1, 0.9)),
drawLine(vec2(0.1, 0.9), vec2(0.7, 0.5))),
drawLine(vec2(0.1, 0.1), vec2(0.7, 0.5))));
}
另一种选择是使用texture2D
检查附近像素的颜色 - 这样你可以让你的图像发光或变厚(例如,如果任何调整像素是白色的 - 使当前像素为白色,如果附近像素为白色 - 使当前像素像素灰色)。
这是我的方法。 设 p1 和 p2 是定义线的两个点,点是您要测量的到该线的距离的点。 点很可能是 gl_FragCoord.xy / resolution;
这是功能。
float distanceToLine(vec2 p1, vec2 p2, vec2 point) {
float a = p1.y-p2.y;
float b = p2.x-p1.x;
return abs(a*point.x+b*point.y+p1.x*p2.y-p2.x*p1.y) / sqrt(a*a+b*b);
}
然后在您的 mix 和 smoothstep 函数中使用它。
另请查看此答案: https : //stackoverflow.com/a/9246451/911207
一个简单的技巧是在顶点着色器中添加一个抖动: gl_Position += vec4(delta, delta, delta, 0.0); 其中 delta 是像素大小,即 1.0/viewsize
使用零进行两次画线传递,然后将增量作为抖动(作为均匀传入)。
要在 Fragment Shader 中画一条线,我们应该检查当前像素 (UV) 是否在线条位置上。 (仅使用 Fragment 着色器代码效率不高!这仅用于使用 glslsandbox 进行测试)可接受的 UV 点应具有以下两个条件:
1- (uv, pt1) 之间的最大允许距离应小于 (pt1, pt2) 之间的距离。 在这种情况下,我们创建了一个以 pt2 为中心的假定圆,radius = distance(pt2, pt1) 并且还防止绘制比 distance(pt2, pt1) 长的线。
2- 对于每个 UV,我们假设一个假想的圆,在线 (pt2,pt1) 的 ptc 位置上有一个连接点。 如果 UV 和 PTC 之间的距离小于线刻度,我们选择此 UV 作为线点。
在我们的代码中:r = distance (uv, pt1) / distance (pt1, pt2) 给我们一个介于 0 和 1 之间的值。我们用 r 值在 pt1 和 pt2 之间插入一个点 (ptc)
代码:
#ifdef GL_ES
precision mediump float;
#endif
uniform float time;
uniform vec2 mouse;
uniform vec2 resolution;
float line(vec2 uv, vec2 pt1, vec2 pt2,vec2 resolution)
{
float clrFactor = 0.0;
float tickness = 3.0 / max(resolution.x, resolution.y); //only used for tickness
float r = distance(uv, pt1) / distance(pt1, pt2);
if(r <= 1.0) // if desired Hypothetical circle in range of vector(pt2,pt1)
{
vec2 ptc = mix(pt1, pt2, r); // ptc = connection point of Hypothetical circle and line calculated with interpolation
float dist = distance(ptc, uv); // distance betwenn current pixel (uv) and ptc
if(dist < tickness / 2.0)
{
clrFactor = 1.0;
}
}
return clrFactor;
}
void main()
{
vec2 uv = gl_FragCoord.xy / resolution.xy; //current point
//uv = current pixel
// 0 < uv.x < 1 , 0 < uv.x < 1
// left-down= (0,0)
// right-top= (1,1)
vec2 pt1 = vec2(0.1, 0.1); //line point1
vec2 pt2 = vec2(0.8, 0.7); //line point2
float lineFactor = line(uv, pt1, pt2, resolution.xy);
vec3 color = vec3(.5, 0.7 , 1.0);
gl_FragColor = vec4(color * lineFactor , 1.);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.