避免在圆角几何着色器中分支

问题描述

我制作了一个 glsl 几何着色器,它可以使 2D 线条的角变圆。着色器在每个角插入圆形圆角。

有一种特殊情况,即两个相邻线段共线且无法创建圆角。在这种情况下,只传递一个原始顶点。

这需要对每个输入顶点执行一个 if 语句。在这种特殊情况下,有没有一种聪明的方法可以避免分支?如果每帧处理的顶点总数通常在几百个左右,这甚至是一个问题吗?

这是完整的着色器代码

#version 400

layout(lines_adjacency) in;
layout(line_strip,max_vertices=25) out;

uniform mat4 modelMatrix;
uniform mat4 viewMatrix;
uniform mat4 projectionMatrix;
uniform float radius = 160.0;
uniform int steps = 10;

in VS_OUT {
    vec2 position;
} gsIn[];


bool arc(vec2 p0,vec2 p1,vec2 p2,out vec2 arcCenter,out vec2 arcStartPoint,out vec2 arcMidPoint,out vec2 arcEndPoint){
    vec2 t0 = normalize(p0 - p1);
    vec2 t1 = normalize(p2 - p1);   
    
    // segments are colinear,exit
    if(abs(dot(t0,t1)) > .9999f){
        return false;
    }

    vec2 h = normalize((t0 + t1) /2.0);
    float cosa = abs(dot(h,vec2(-t0.y,t0.x)));
    float hlen = radius/cosa;

    arcCenter = p1 + h*hlen;     
    
    float d = sqrt(hlen*hlen - radius*radius);  

    arcStartPoint  = p1 + t0 * d;
    arcEndPoint = p1 + t1 *d;
    arcMidPoint = arcCenter - h * radius;
    return true;
} 

float stepangle(vec2 center,vec2 s,vec2 e){
    vec2 rv1 = s-center;
    vec2 rv2 = e-center;
    float angle = acos( dot(normalize(rv1),normalize(rv2)) ) / steps;
    if( dot(rv1,vec2(-rv2.y,rv2.x))<0 ){
        angle = -angle;
    }
    return angle;
}

mat2 rotationMatrix(float angle){
    float cosa = cos(angle);
    float sina = sin(angle);
    return mat2(cosa,-sina,sina,cosa);
}

void emitFillet(vec2 center,vec2 arcStartPoint,vec2 arcEndPoint,mat4 mvpMatrix){
    float a = stepangle(center,arcStartPoint,arcEndPoint);
    mat2 rotMat = rotationMatrix(a);
    vec2 radVec = arcStartPoint-center;

    for(int i=0; i <=steps ; ++i){
        gl_Position = mvpMatrix * vec4(center + radVec,0.0,1.0);
        EmitVertex();
        radVec = rotMat * radVec;
    }
}

void emitSingLevertex(vec2 vert,mat4 mvpMatrix){
    gl_Position = mvpMatrix * vec4(vert,1.0);
    EmitVertex();
}

void main(){    

    mat4 mvMatrix = viewMatrix * modelMatrix;
    mat4 mvpMatrix = projectionMatrix * mvMatrix;

    vec2 p0 = gsIn[0].position;
    vec2 p1 = gsIn[1].position;
    vec2 p2 = gsIn[2].position;
    vec2 p3 = gsIn[3].position;

    vec2 center,s,m,e;
    mat2 rotMat;
    vec2 radVec;
    float a;
    bool canMakeFillet;

    // first corner half-fillet
    canMakeFillet = arc(p0,p1,p2,center,e);
    if(canMakeFillet){
        emitFillet(center,e,mvpMatrix);
    }
    else{
        emitSingLevertex(p1,mvpMatrix);
    }
    
    // scond corner half-fillet
    canMakeFillet = arc(p1,p3,mvpMatrix);
    }
    else{
        emitSingLevertex(p2,mvpMatrix);
    }
    
    EndPrimitive();
}

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...