微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何使用 XRenderCompositeTriangles 渲染两个相邻的三角形?

如何解决如何使用 XRenderCompositeTriangles 渲染两个相邻的三角形?

我正在尝试使用 XRender 中的三角形基元来绘制描边线。根据(相当有限的)documentation(见第 10 节):

邻接边缘必须精确匹配。指定两个沿公共线邻接的多边形时 边,如果该边在每个多边形中使用相同的坐标指定,则两个多边形并集内像素的 alpha 值之和必须恰好为 1。

在我看来,这意味着如果我渲染一个镶嵌成两个三角形的白色方块,所有像素——尤其是沿边界的像素——都应该是白色的。但是,我发现三角形实际上并没有完全接触。以下代码导致输出

000 000 000 000 000 000 000 000 000 000 000 000 000
000 000 000 000 000 000 000 000 000 000 000 000 000
000 000 fff fff fff fff fff fff fff fff ccc 000 000
000 000 fff fff fff fff fff fff fff ddd fff 000 000
000 000 fff fff fff fff fff fff eee eee fff 000 000
000 000 fff fff fff fff fff fff ddd fff fff 000 000
000 000 fff fff fff fff fff ccc fff fff fff 000 000
000 000 fff fff fff fff bbb fff fff fff fff 000 000
000 000 fff fff fff ccc fff fff fff fff fff 000 000
000 000 fff fff ddd fff fff fff fff fff fff 000 000
000 000 fff eee eee fff fff fff fff fff fff 000 000
000 000 fff ccc fff fff fff fff fff fff fff 000 000
000 000 ccc fff fff fff fff fff fff fff fff 000 000
000 000 000 000 000 000 000 000 000 000 000 000 000
000 000 000 000 000 000 000 000 000 000 000 000 000

我期望矩形中的所有点都是 fff,因为沿边缘的坐标是相同的,所以两个三角形(矩形)的并集内的所有像素应该是“精确的一”。看起来这是一个必不可少的品质,否则三角形没有多大用处;如果三角形离开边界,那么你不能镶嵌任何东西。所以我希望我做错了什么,但我不知道是什么。

#include <X11/Xlib.h>
#include <X11/extensions/Xrender.h>

#include <algorithm>
#include <iostream>
#include <string>
#include <vector>

XRenderColor makeColor(float r,float g,float b,float a = 1.0f)
{
    unsigned short ur = (unsigned short)std::min(65535.0f,r * 65536.0f);
    unsigned short ug = (unsigned short)std::min(65535.0f,g * 65536.0f);
    unsigned short ub = (unsigned short)std::min(65535.0f,b * 65536.0f);
    unsigned short ua = (unsigned short)std::min(65535.0f,a * 65536.0f);
    return { ur,ug,ub,ua };
}

XTriangle makeTri(float x1,float y1,float x2,float y2,float x3,float y3)
{
    XTriangle tri;
    tri.p1.x = XDoubletoFixed(x1);
    tri.p1.y = XDoubletoFixed(y1);
    tri.p2.x = XDoubletoFixed(x2);
    tri.p2.y = XDoubletoFixed(y2);
    tri.p3.x = XDoubletoFixed(x3);
    tri.p3.y = XDoubletoFixed(y3);
    return tri;
}

int main(int argc,char *argv[])
{
    const int width = 13;
    const int height = 15;

    auto *display = XOpendisplay(nullptr);

    // Create destination pixmap
    auto pictFormat = XRenderFindStandardFormat(display,PictStandardARGB32);
    auto drawable = XRootwindow(display,XDefaultScreen(display));
    auto pixmap = XCreatepixmap(display,drawable,width,height,32);

    // Create XRender picture
    XRenderPictureAttributes attr;
    attr.poly_edge = polyEdgeSmooth;
    attr.poly_mode = polyModeImprecise;
    auto drawArea = XRenderCreatePicture(display,pixmap,pictFormat,CPpolyEdge | CPpolyMode,&attr);

    // Clear pixmap to black
    auto bgColor = makeColor(0.0f,0.0f,0.0f);
    XRenderFillRectangle(display,PictOpSrc,drawArea,&bgColor,height);

    // Draw rectangle with two triangles in white
    float ul[2] = { 2.0f,2.0f };
    float ur[2] = { 11.0f,2.0f };
    float ll[2] = { 2.0f,13.0f };
    float lr[2] = { 11.0f,13.0f };
    std::vector<XTriangle> tris;
    tris.push_back(makeTri(ll[0],ll[1],lr[0],lr[1],ur[0],ur[1]));
    tris.push_back(makeTri(ll[0],ur[1],ul[0],ul[1]));

    auto fgColor = makeColor(1.0f,1.0f,1.0f);
    auto fg = XRenderCreateSolidFill(display,&fgColor);
    XRenderCompositeTriangles(display,PictOpOver,fg,nullptr,tris.data(),tris.size());

    XSync(display,pixmap);
    auto readablecopy = XGetimage(display,0xffffffff,Zpixmap);
    const char kHex[] = "0123456789abcdef";
    for (int y = 0; y < height; ++y) {
        std::string s = "";
        for (int x = 0; x < width; ++x) {
            unsigned long pixel = XGetPixel(readablecopy,x,y);
            unsigned char a = (pixel & 0xff000000) >> 24;
            unsigned char r = (pixel & 0x00ff0000) >> 16;
            unsigned char g = (pixel & 0x0000ff00) >> 8;
            unsigned char b = (pixel & 0x000000ff);
            s += kHex[int(r / 16)];
            s += kHex[int(g / 16)];
            s += kHex[int(b / 16)];
            s += " ";
        }
        std::cout << s << std::endl;
    }

    XDestroyImage(readablecopy);
    XFreepixmap(display,pixmap);
    XClosedisplay(display);

    return 0;
}

我做错了什么?

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。