首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用着色程序的最有效的线条算法是什么?

使用着色程序的最有效的线条算法是什么?
EN

Computer Graphics用户
提问于 2021-02-20 16:45:08
回答 1查看 1.2K关注 0票数 0

我对着色器很陌生,我一直在尝试在着色玩具中使用它们。我正试图对图形管道有更深入的了解,我想用着色器实现一些功能。我想从简单的开始,用着色器在屏幕上画一条线。我从头开始写了两行算法

代码语言:javascript
复制
struct Vertex {
    vec2 p;
    vec4 c;
};

vec4 overlay(vec4 c1, vec4 c2) {
    return vec4((1.0 - c2.w) * c1.xyz + c2.w * c2.xyz, 1.0);
}

vec4 drawLineA(Vertex v1, Vertex v2, vec2 pos) {
    vec2 a = v1.p;
    vec2 b = v2.p;
    vec2 r = floor(pos);
    
    vec2 diff = b - a;
    
    
    if (abs(diff.y) < abs(diff.x)) {
        if (diff.x < 0.0) {
            Vertex temp1 = v1;
            Vertex temp2 = v2;
            
            v1 = temp2;
            v2 = temp1;
            
            a = v1.p;
            b = v2.p;
            diff = b - a;
        
        }
        
        float m = diff.y / diff.x;
        float q = r.x - a.x;
        
        if (floor(m * q + a.y) == r.y && a.x <= r.x && r.x <= b.x) {
            float h = q / diff.x;
            return vec4((1.0 - h) * v1.c + h * v2.c);
        }
        
        
    } else {
        if (diff.y < 0.0) {
            Vertex temp1 = v1;
            Vertex temp2 = v2;
            
            v1 = temp2;
            v2 = temp1;
            
            a = v1.p;
            b = v2.p;
            diff = b - a;
        
        }
    
        float m =  diff.x / diff.y;
        float q = r.y - a.y;
        
        if (floor(m * q + a.x) == r.x && a.y <= r.y && r.y <= b.y) {
            float h = q / diff.y;
            return vec4((1.0 - h) * v1.c + h * v2.c);
        }
    
    }
    
    return vec4(0,0,0,0);
}

vec4 drawLineB(Vertex v1, Vertex v2, vec2 pos) {
    vec2 a = v1.p;
    vec2 b = v2.p;
    
    vec2 l = b - a;
    vec2 r = pos - a;
    float h = dot(l,r) / dot (l,l);
    
    vec2 eC = a + h * l;
    
    if (floor(pos) == floor(eC) && 0.0 <= h && h <= 1.0 ) {
       return vec4((1.0 - h) * v1.c + h * v2.c); 
    }
    
    return vec4(0,0,0,0);
}



void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    float t = iTime;
    float r = 300.0;
    Vertex v1 = Vertex(vec2(400,225), vec4(1,0,0,1));
    Vertex v2 = Vertex(vec2(400.0 + r*cos(t) ,225.0 + r*sin(t)), vec4(0,1,0,1));
    
    vec4 col = vec4(0,0,0,1);
    col = overlay(col,drawLineA(v1, v2, fragCoord));
    col = overlay(col,drawLineB(v1, v2, fragCoord));
    // Output to screen
    fragColor = col;
}

但是,它们都很慢,是否有一个更有效的线算法,我可以用它来根据像素是否在线上输出颜色。我听说Bresenham的直线算法是最快的,但是我不知道如何使用着色器来加速算法,因为它需要前面的y值来计算下一个。行算法可以通过着色器加速,或者它已经是CPU上最快的了。如果有一个使用GPU ( GPU将优于cpu)的优化绘制算法,我如何将其实现到代码中?

谢谢

EN

回答 1

Computer Graphics用户

发布于 2021-02-21 01:07:18

以下是SDF的一个(主要是)最小版本,用于使用带符号距离字段的线段,如注释中所建议的那样。我不相信这个代码,它是您的功能拼凑在一起的IQ的SDF功能所做的风格,你上面列出的。

一定要去IQ的网站,这是最好的学习资源之一,为这方面的材料。不过,除非你把所有的基本知识都弄下来,否则就很难消化。智商指数页。

代码语言:javascript
复制
float udSegment( in vec2 p, in vec2 a, in vec2 b )
{
   vec2 ba = b-a;
   vec2 pa = p-a;
   float h =clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0 );
   //return length(pa-h*ba); // use actual length

   // or use length squared
   vec2 sqrd = pa-h*ba;
   sqrd = sqrd * sqrd;
   return sqrd.x+sqrd.y;
}

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
   vec2 p = ((2.0*fragCoord-iResolution.xy)/iResolution.y)*1.4;

    // give it some spin
    vec2 v1 = iResolution.xy * vec2(cos(iTime),sin(iTime));

    vec2 v2 = vec2(0,0); // set the start point
    float th = 0.004; // Controls line thickness

    float d = udSegment( p, v1, v2 ) - th; // compute sdf

    vec3 col = vec3(1.0) - sign(d);
    fragColor = vec4(col,1.0);
}

如果所有这些都是画一条线,那么就不需要计算实际长度,所以不要.只返回长平方。我对上面跳过sqrt的代码进行了编辑,但是行厚现在是平方的。

Bresenham算法是用来绘制单个像素的,通常直接在GPU的硬件中实现,因此它驱动在自己的循环中绘制哪些像素,并告诉硬件要绘制哪个像素。

ShaderToy正在绘制整个屏幕,因此每个像素都可能通过绘制全屏三角形来覆盖,然后在碎片着色器中调用mainImage函数。

在GPU上绘制线的最有效的方法是根本不使用ShaderToy,而是编写我们自己的代码,告诉硬件只画一条线,这就是图形API(如OpenGL )发挥作用的地方。它最终会调用片段着色器,但与ShaderToy不同的是,片段着色器只会被调用到那些实际处于线上的片段,然后我们的片段着色器将被简化为一些非常简单的东西,比如:

代码语言:javascript
复制
void main(){ return vec4(1,1,1,1); }

这将导致在屏幕上画一条纯白线。

票数 1
EN
页面原文内容由Computer Graphics提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://computergraphics.stackexchange.com/questions/10682

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档