繁体   English   中英

在 OpenGL 片段着色器中绘制三角形

[英]Drawing a triangle in OpenGL fragment shader

我正在尝试使用 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));
}

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

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

其中C(n)表示:“是边 n 正确一侧的点”

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

或者,您可以使用重心技术进行测试。

请参阅:此网站了解更多详情。

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

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

  1. 计算片段的重心s,t坐标

    当你在 GLSL 中得到mat3,vec3 ,去使用矩阵方法......

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

    简单地通过测试s+t<=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进行纹理化(甚至是程序化的)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM