使用片段着色器在特定位置绘制完美的水平线

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用片段着色器在特定位置绘制完美的水平线相关的知识,希望对你有一定的参考价值。

是否可以在垂直轴上的任何选定位置绘制单个像素高度的完美水平线,并将片段着色器应用于屏幕对齐的四边形?

我找到了许多具有smoothstep或更复杂功能的解决方案,但我正在寻找一种优雅而快速的方法。

我所做的一个解决方案是使用指数函数并使其更陡峭,但它有许多我不想要的缺点(由于指数函数,该行不是真正的一个像素高度,并且获得一个正确是相当棘手的) ,这是GLSL代码:

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    vec2 uv = fragCoord.xy / iResolution.xy;

    // a centered horizontal line
    float v = pow(uv.y - 0.5, 2.);

    // make it steeper
    v *= 100000.;

    // make it white on a black background
    v = clamp(1. - v, 0., 1.);

    fragColor = vec4(v);
}

这是执行此操作的shadertoy代码:https://www.shadertoy.com/view/Ms2cWh

我想要的是什么:

  • 以像素为单位绘制到特定Y位置或标准化的完美水平线
  • 其强度限制在[0,1]范围内,无需夹紧
  • 快速做到这一点
答案

如果你只想:

在垂直轴上的任何选定位置绘制单个像素高度的完美水平线,并将片段着色器应用于屏幕对齐的四边形

那么也许:

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    int iPosition = 250; // the y coord in pixels
    int iThickness = 10; // the thickness in pixels

    vec2 uv = fragCoord.xy / iResolution.xy;

    float v = float( iPosition ) / iResolution.y;
    float vHalfHeight = ( float( iThickness ) / ( iResolution.y ) ) / 2.;

    if ( uv.y > v - vHalfHeight && uv.y < v + vHalfHeight )
        fragColor = vec4(1.,1.,1.,1.); // or whatever color
}
另一答案

Here是一个没有分支的整洁解决方案。我不知道它是否真的比分支更快。

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    vec2 uv = fragCoord.xy / iResolution.xy;

    float py = iMouse.y/iResolution.y;

    float hh = 1./iResolution.y;

    // can also be replace with step(0., hh-abs(uv.y-py))
    float v = sign(hh-abs(uv.y-py));

    fragColor = vec4(v);
}
另一答案

我知道问题在我面前得到了适当的回答,但是如果有人正在寻找一种以像素完美的方式渲染纹理线的方法,我会用一些例子写一个article

它通常是像素完美的UI,但将它用于线条只是夹紧/重复纹理采样的问题。我也使用Unity,但没有理由这个方法是独占的。

以上是关于使用片段着色器在特定位置绘制完美的水平线的主要内容,如果未能解决你的问题,请参考以下文章

GLSL片段着色器 - 绘制简单的粗曲线

GLSL片段着色器-绘制简单的粗曲线

OpenGL 片段着色器未写入 fbo 颜色缓冲区

如何避免使用着色器在 OpenGL 中消失线?

GLSL-片段着色器不同部分的精度不同

纹理上的片段着色器