【问题标题】:how to offset a 2D triangle in a webgl shader?如何在 webgl 着色器中偏移 2D 三角形?
【发布时间】:2015-09-11 12:53:08
【问题描述】:

我认为我有一个愚蠢的案例,我计划实施一些保守的深度渲染 (conservative rendering in CPU gems),但我被困在最基本的水平:放大三角形。

这里是事态: http://nraynaud.github.io/webgcode/test_3D_conservative_rendering.html (黑色三角为输入,红点为放大顶点,正方形代表采样网格)

我将 webgl 与 thee.js 一起使用,我将每个顶点的 2 个伴随顶点作为属性发送,并且我正在尝试放大顶点着色器中的三角形。我处于最愚蠢的情况:我有一个正交相机,它的“向上”是+Y 轴,并且视图向-Z 延伸(基本上我正在拍摄我的脚,屏幕顶部是+Y)。我不能(我认为,投影几何有点神秘)直接使用来自 CPU gems 的代码,因为它假设一个透视相机(它计算通过三角形边缘的平面和观察者的眼点,而Ortho没有眼点)。

这是我尝试过的:

        '    vec3 p1 = prevPoint, p2 = position, p3 = nextPoint;',
        '    if (!isFrontFacing(p1.xy, p2.xy, p3.xy)) {vec3 temp = p1;p1 = p3; p3 = temp;}',
        //move the vertex in 2D
        '    vec2 e1 = p2.xy - p1.xy;',
        '    vec2 e1Normal = normalize(vec2(e1.y, -e1.x));',
        '    vec2 e1Translate = e1Normal * length(hPixelWorld);',

        '    vec2 e2 = p3.xy - p2.xy;',
        '    vec2 e2Normal = normalize(vec2(e2.y, -e2.x));',
        '    vec2 e2Translate = e2Normal * length(hPixelWorld);',

我认为这应该给我与 p2(考虑的顶点)相邻的 2 条边的 2 条法线,都指向三角形的内部或外部,这取决于我的运气。好吧,实际上,根据考虑的顶点,我并不总是让法线指向同一个方向(而不是缺点),而且我没有解释(我什至试图用 isFrontFacing 来保护我的代码对抗顶点顺序() 在顶部)。

我尝试了一些愚蠢的东西,比如计算法线方向的所有 4 种可能性,并选择让我距离三角形质心最远的点,但我认为我什至搞砸了它的实现,因为有些点是显然不是离中心最远的地方:

        '    vec3 possibilities[4];',
        '    vec2 centroid = ((p1+p2+p3)/3.0).xy;',
        '    possibilities[0] = translatePoint(p2.xy, +e1Translate, +e2Translate, e1, e2, centroid);',
        '    possibilities[1] = translatePoint(p2.xy, -e1Translate, +e2Translate, e1, e2, centroid);',
        '    possibilities[2] = translatePoint(p2.xy, -e1Translate, -e2Translate, e1, e2, centroid);',
        '    possibilities[3] = translatePoint(p2.xy, +e1Translate, -e2Translate, e1, e2, centroid);',
        '    vec3 currentBest = possibilities[0];',
        '    if (possibilities[1].z >= currentBest.z)',
        '        currentBest = possibilities[1];',
        '    if (possibilities[2].z >= currentBest.z)',
        '        currentBest = possibilities[2];',
        '    if (possibilities[3].z >= currentBest.z)',
        '        currentBest = possibilities[3];',

        '    vec2 resultPoint2D = currentBest.xy;',

这里是正面:

        'bool isFrontFacing(vec2 p1, vec2 p2, vec2 p3) {',
        '    float a = cross2d(p2-p1, p2-p3);',
        '    return a > 0.0;',
        '}',

这里是翻译点:

        // we are encoding the distance to centroid in z
        'vec3 translatePoint(vec2 point, vec2 dir1, vec2 dir2, vec2 e1, vec2 e2, vec2 centroid) {',
        '    vec2 e1TranslatedPoint = point + dir1;',
        '    vec2 e2TranslatedPoint = point + dir2;',
        //http://stackoverflow.com/questions/563198/how-do-you-detect-where-two-line-segments-intersect
        '    float u = cross2d(e2TranslatedPoint - e1TranslatedPoint, e2) / cross2d(e2, e1);',
        '    vec2 result = e1TranslatedPoint + u * e1;',
        '    float dist = length(result - centroid);',
        '    return vec3(result, dist);',
        '}',

和cross2D:

        'float cross2d(vec2 v1, vec2 v2) {',
        '    return v1.x * v2.y - v1.y * v2.x; ',
        '}',

这里是完整的代码: https://github.com/nraynaud/webgcode/blob/01550668fdedba5ab61e2fbf5ed9917ca06b5e75/test_3D_conservative_rendering.html

我们看到只有一个顶点在正确的方向上移动,对于其他 2 个,边缘法线之一是错误的。

好的,那么当我们不是几何白痴时,我们如何偏移三角形呢?

【问题讨论】:

    标签: javascript three.js glsl webgl


    【解决方案1】:

    我认为您不需要实际遍历法线方向的所有候选组合 - 由于偏移量沿当前顶点的角平分线,您已经知道实际方向仅来自方向的总和来自其他两个三角形顶点的向量p1p2

    如果你画一个图,你会发现从原始位置偏移的距离与两个方向向量之间夹角一半的正弦成正比。

    float pixelSize = 10.0; // or whatever
    
    void main() { 
        vec3 a = normalize(position - prev);
        vec3 b = normalize(position - next);
    
        // we will offset along the vector `c`
        vec3 c = normalize(a + b);
    
        // a formula to calculate the sine of half an angle
        float halfsine = sqrt((1.0 - dot(a, b)) / 2.0);
    
        gl_Position = vec4(position + pixelSize * c / halfsine, 1);
    }
    

    这是一张餐巾图:向量AB 是其他顶点的归一化方向。 pixel 显示偏移量大小。小直角三角形是全等的,因为新旧顶点位置与两条边线的距离相等。

    【讨论】:

    • 非常非常感谢。我对现在的简单性感到有些羞耻,但至少我确实有一个工作代码。我想我会坚持一个恒定的偏移量(当为每个边缘选择不同的偏移量时,有一种方法可以稍微减少偏移量,但我认为我不会管理它)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多