【问题标题】:Drawing a triangle in OpenGL fragment shader在 OpenGL 片段着色器中绘制三角形
【发布时间】:2020-11-06 17:38:27
【问题描述】:

我正在尝试使用 OpenGL 片段着色器绘制三角形。

我成功地画了一个圆,但我在处理等式/逻辑或绘制三角形的代码时遇到了问题。

draw_triangle(vec2 v1 , vec2 v2, vec2 v3)

这是片段着色器:

#version 330 core

out vec4 frag_color;

void draw_circle(vec2 shift_val, int radius,int color)
{
    vec2 res = vec2(1280,720);
    vec2 norm_cord = gl_FragCoord.xy;
    float dist = length(norm_cord - (res*shift_val));
    if( dist < radius )
    {
        if( color ==1 )
            frag_color = vec4(1.0, 1.0, 1.0, 1.0);
            else
            frag_color = vec4(0.0, 0.0, 0.0, 1.0);
    }
}

void draw_triangle(vec2 v1 , vec2 v2, vec2 v3)
{
    vec2 res = vec2(1280,720)*vec2(0.58,0.4);
    vec2 v = vec2(gl_FragCoord.x,gl_FragCoord.y);

    float slope1 = abs((v1.y-v2.y)/(v1.x-v2.x)); //y2-y1/x2-x1
    float slope2 = abs((v2.y-v3.y)/(v2.x-v3.x)); //y2-y1/x2-x1
    float slope3 = abs((v1.y-v3.y)/(v1.x-v3.x)); //y2-y1/x2-x1

    float slope_ref1 = abs((v.y-v1.y)/(v.x-v1.x)); //y2-y1/x2-x1
    float slope_ref2 = abs((v.y-v2.y)/(v.x-v2.x)); //y2-y1/x2-x1
    float slope_ref3 = abs((v.y-v3.y)/(v.x-v3.x)); //y2-y1/x2-x1

    float slope_RES1 = abs((res.y-v1.y)/(res.x-v1.x)); //y2-y1/x2-x1
    float slope_RES2 = abs((res.y-v2.y)/(res.x-v2.x)); //y2-y1/x2-x1
    float slope_RES3 = abs((res.y-v3.y)/(res.x-v3.x)); //y2-y1/x2-x1

    if (slope_RES1 < slope1 )
    {
        if(slope_ref1 < slope1)// && slope_ref3 < slope2 )//slope_ref1 < slope1 &&
            frag_color = vec4(1.0, 0.0, 1.0, 1.0);
    }

    if (slope_RES2 > slope2)
        {
            if(slope_ref2 > slope2)
                frag_color = vec4(1.0, 0.5, 1.0, 1.0);
        }

    /*if (slope_RES3 < slope3)
        {
            if(slope_ref3 > slope3)
                frag_color = vec4(1.0, 0.0, 1.0, 1.0);
        }*/
}

// This is entry point of the fragment shader and it will be called for every fragment covered by the rasterized geometry
void main() {
    // Here we just output a constant color which is red (R=1, G=0, B=0, A=1)
    //frag_color = vec4(0.0, 0.0, 0.0, 1.0);
    draw_circle(vec2(0.5,0.5),100,1); //draws face of circle
    draw_circle(vec2(0.5,0.58),16,0); //draws eye (1 for white and anynumber for black)
    draw_triangle(vec2(0.5f,0.5f),vec2(-0.5,0.0f),vec2(0.5f,-0.5f));
}

【问题讨论】:

标签: opengl glsl 2d fragment-shader


【解决方案1】:

要使用同一边技术计算一个点是否在三角形中,您需要针对三条线测试候选点,以查看它在每条线的哪一边。如果它满足所有三条线的边度测试,则它在三角形内。

条件测试将是C(0) &amp;&amp; C(1) &amp;&amp; C(2)

其中C(n)的意思是:“是边n正确边上的点”

条件“AB 的哪一侧是点 X”通常通过检查 AB × AX叉积 的符号来检查。按照惯例,您可以为您的三角形分配一个缠绕顺序,并始终检查该叉积的符号是否为正。 当然,这取决于三角形顶点的缠绕顺序。 (例如,顺时针顶点需要负叉积,逆时针顶点需要正叉积。根据多边形的定义选择您喜欢或最方便的约定。)

您也可以使用重心技术进行测试。

有关详细信息,请参阅:this site

【讨论】:

  • 这是一个很好的答案。我要补充一点,这里的叉积相当于外积/楔积AB ∧ AX,它的优点是它只是2D,不需要使用3D向量。
  • 我听从了你的建议,但我无法达到预期的输出 ``` vec2 v = vec2(gl_FragCoord.x,gl_FragCoord.y); vec2 AB = vec2(b.x-a.x,b.y-a.y); vec2 BC = vec2(c.x-b.x,c.y-b.y); vec2 CA = vec2(a.x-c.x,a.y-c.y); vec2 Av = vec2(v.x-a.x,v.y-a.y); vec2 Bv = vec2(v.x-b.x,v.y-b.y); vec2 Cv = vec2(v.x-c.x,v.y-c.y);浮动轴= AB.x * Av.y - AB.y * Av.x;浮动 bx= BC.x * Bv.y - BC.y * Bv.x;浮动 cx= CA.x * Cv.y - CA.y * Cv.x; if (ax
  • @GeorgeMaher 在 cmets 中使用单个 ` 而不是 ``` 来封装 code,因此您还有更多字符。还要注意代码和`或```之间不能有空格,否则它将无法正常工作,就像您最后的评论一样
  • 对于着色器,您必须有条不紊地进行小改动和大量测试。你能让它呈现纯白色吗?如果是这样,那么慢慢地对着色器进行增量更改,直到找到你做错的部分。你得到编译错误吗?你有坐标错误吗?什么不适合你?
【解决方案2】:

希望您正在渲染覆盖视图/屏幕的 QUAD...

渲染三角形的片段着色器友好方式是:

  1. 计算片段的barycentric s,t coordinates

    在 GLSL 中使用 mat3,vec3 时采用矩阵方法 ...

  2. 决定是在里面还是在外面

    只需测试s+t&lt;=1.0

  3. 然后设置输出颜色或discard;

    但是丢弃不是你的选择,因为你有更多的形状......

所以计算:

--------------------------------------------------------
| s |           | (p1.a - p0.a) , (p2.a - p0.a) , p0.a |   | p.a |
| t | = inverse | (p1.b - p0.b) , (p2.b - p0.b) , p0.b | * | p.b |
| 1 |           |       0       ,       0       ,   1  |   |  1  |
------------------------------------------------------------------
if (s+t<=1.0) set output color

您还可以使用s,t 进行纹理化(甚至是程序化纹理)。

【讨论】:

    猜你喜欢
    • 2017-05-16
    • 2017-04-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-12
    • 2020-11-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多