Graphics 非抗锯齿线和锯齿线的最佳算法是什么

Graphics 非抗锯齿线和锯齿线的最佳算法是什么,graphics,glsl,shader,line,fragment-shader,Graphics,Glsl,Shader,Line,Fragment Shader,我是shaders的新手,我一直在和shadertoy网站玩。我试图理解图形(和图形管道),如绘制线、插值、光栅化等。。。我编写了两个线条函数,如果处理的像素在线条上,它们将返回颜色。这是使用片段着色器的着色器代码 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); } v

我是shaders的新手,我一直在和shadertoy网站玩。我试图理解图形(和图形管道),如绘制线、插值、光栅化等。。。我编写了两个线条函数,如果处理的像素在线条上,它们将返回颜色。这是使用片段着色器的着色器代码

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;
}
struct顶点{
vec2p;
vec4;
};
vec4覆盖(vec4 c1,vec4 c2){
返回向量4((1.0-c2.w)*c1.xyz+c2.w*c2.xyz,1.0);
}
vec4拉线A(顶点v1、顶点v2、vec2位置){
vec2a=v1.p;
vec2b=v2.p;
vec2 r=楼层(位置);
vec2-diff=b-a;
if(abs(diff.y)如果(floor(m*q+a.y)=r.y&&a.x碎片着色器确实不是正确的方法,那么shadertoy上的很多内容实际上只是一个玩具/代码高尔夫游戏,展示了克服平台局限性的解决方案,这些局限性在现实场景中效率极低

所有图形API都为绘制线段提供了专用接口,只需搜索“API_NAME draw line”,例如“webgl draw line”。如果这些图形API不足以绘制带有MSAA或自定义着色器AA的三角形条带,则会使用这些图形API


如果你真的只是在寻找一种有效的算法,你已经介绍过了。

片段着色器确实不是解决这个问题的正确方法,shadertoy上的很多内容实际上只是一个玩具/代码高尔夫游戏,展示了克服平台局限性的解决方案,这些局限性在现实场景中非常低效

所有图形API都为绘制线段提供了专用接口,只需搜索“API_NAME draw line”,例如“webgl draw line”。如果这些图形API不足以绘制带有MSAA或自定义着色器AA的三角形条带,则会使用这些图形API


如果你真的只是在寻找一种有效的算法,你已经介绍过了。

因为另一个答案说着色器在这方面不是很好

现在,线光栅化是在幕后使用gfx卡上的HW插值器完成的。着色器会为渲染原语的每个像素调用,在您的情况下,这意味着它会为屏幕的每个像素调用,而这一切都会为渲染的每一条线调用,渲染速度大大低于原生方式

如果你真的想学习光栅化,可以在CPU端进行。线条的最佳算法取决于你使用的计算硬件架构

对于顺序处理,它是:

  • 这个是亚像素精度的
在过去,Bresenham的速度更快,但这不是自x386以来IIRC的真实情况

对于并行处理您只需计算像素到直线的距离(或多或少像现在这样)

因此,如果您坚持使用着色器进行此操作,您可以使用几何体着色器加快速度,并仅处理线条附近的片段(像素)。请参阅:

所以,只需围绕直线创建OOBB,并通过每直线发射2个三角形进行渲染,然后在片段中计算到直线的距离,并相应地设置颜色

对于抗锯齿,您只需更改最后一个像素边缘距离上像素的颜色。因此,如果您的线条有一半宽度
w
,并且片段到线条的距离为
d
,则:

if (d>w) discard; // fragment too far
d=(w-d)/pixel_size; // distance from edge in pixels
frag_color = vec4(r,g,b,min(1.0,d)); // use transparency/blending 
正如您所看到的,抗锯齿只是通过混合进行渲染(由亚像素位置/像素相对于光栅化对象的距离进行调制),DDA也可以使用相同的技术


也有渲染线的光线跟踪方法,但它们与查找到线的距离几乎相同……但是,与2D像素位置相比,您可以检查3D光线的位置,这会使数学稍微复杂化。

,因为另一个答案说,着色器在这方面不是很好

现在,线光栅化是在幕后使用gfx卡上的HW插值器完成的。着色器会为渲染原语的每个像素调用,在您的情况下,这意味着它会为屏幕的每个像素调用,而这一切都会为渲染的每一条线调用,渲染速度大大低于原生方式

如果你真的想学习光栅化,可以在CPU端进行。线条的最佳算法取决于你使用的计算硬件架构

对于顺序处理,它是:

  • 这个是亚像素精度的
在过去,Bresenham的速度更快,但这不是自x386以来IIRC的真实情况

对于并行处理您只需计算像素到直线的距离(或多或少像现在这样)

因此,如果您坚持使用着色器进行此操作,您可以使用几何体着色器加快速度,并仅处理线条附近的片段(像素)。请参阅:

所以,只需围绕直线创建OOBB,并通过每直线发射2个三角形进行渲染,然后在片段中计算到直线的距离,并相应地设置颜色

对于抗锯齿,您只需更改最后一个像素边缘距离上像素的颜色。因此,如果您的线条有一半宽度
w
,并且片段到线条的距离为
d
,则:

if (d>w) discard; // fragment too far
d=(w-d)/pixel_size; // distance from edge in pixels
frag_color = vec4(r,g,b,min(1.0,d)); // use transparency/blending 
正如您所看到的,抗锯齿只是通过混合进行渲染(由亚像素位置/像素相对于光栅化对象的距离进行调制),DDA也可以使用相同的技术

也有渲染线的光线跟踪方法,但它们与查找到线的距离几乎相同…但是,与2D像素位置不同,您可以根据3D光线进行检查,这会稍微复杂化