Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/opengl/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 有符号距离字段的Alpha测试文本渲染创建扭曲的边_C++_Opengl_Textures_Distance_Text Rendering - Fatal编程技术网

C++ 有符号距离字段的Alpha测试文本渲染创建扭曲的边

C++ 有符号距离字段的Alpha测试文本渲染创建扭曲的边,c++,opengl,textures,distance,text-rendering,C++,Opengl,Textures,Distance,Text Rendering,我试图在我的应用程序中使用符号距离场纹理表示的glyph atlas渲染文本,这意味着在每个像素中存储到最近轮廓的距离的纹理。 此距离场纹理是使用此算法从原始二进制glyph atlas纹理(0-轮廓线外,1-轮廓线内)生成的,该算法搜索纹理中每个像素周围的增量半径,直到找到状态相反的像素,然后存储找到该像素的距离。之后,所有距离都映射到0和1之间 //set size of signed distance field atlas atlas.width = binaryAtlasWidth*

我试图在我的应用程序中使用符号距离场纹理表示的glyph atlas渲染文本,这意味着在每个像素中存储到最近轮廓的距离的纹理。 此距离场纹理是使用此算法从原始二进制glyph atlas纹理(0-轮廓线外,1-轮廓线内)生成的,该算法搜索纹理中每个像素周围的增量半径,直到找到状态相反的像素,然后存储找到该像素的距离。之后,所有距离都映射到0和1之间

//set size of signed distance field atlas
atlas.width = binaryAtlasWidth* pDistanceFieldResolution;
atlas.height = binaryAtlasHeight * pDistanceFieldResolution;

const unsigned int atlasPixelCount = (atlas.width * atlas.height);
atlas.buffer.resize(atlasPixelCount);

//temporary buffer for the distances of each pixel
std::vector<float> unmappedBuffer;
unmappedBuffer.resize(atlasPixelCount);
//support multisampling
unsigned int samplesPerOutPixel = ceil(1.0 / pDistanceFieldResolution);

//for mapping the values between 0 and 1 later
float maxDistance = 0.0;
float minDistance = 0.0;

for (unsigned int outPixel = 0; outPixel < atlasPixelCount; ++outPixel) {
    //coordinate of the input sample
    unsigned int outPixelX = outPixel%atlas.width;
    unsigned int outPixelY = outPixel/atlas.width;

    float distanceSum = 0.0f;

    for (unsigned int sampleY = 0; sampleY < samplesPerOutPixel; ++sampleY) {
        for (unsigned int sampleX = 0; sampleX < samplesPerOutPixel; ++sampleX) {

            glm::uvec2 sampleCoord = glm::uvec2(outPixelX * samplesPerOutPixel+ sampleX, outPixelY * samplesPerOutPixel+ sampleY);
            unsigned int samplePos = sampleCoord.x + sampleCoord.y*binaryAtlasWidth;
            unsigned char sampleVal = buffer[samplePos];
            //inital distance is maximum search radius(outside of glyph)
            float dist = spread;
            int found = 0;
            unsigned int rad = 0;
            while(!found && (rad*(!sampleVal)) < spread_pixels) {
                //if sampleVal is 1(inside), search until found
                float radius = (float)rad + 1.0f;
                unsigned int compareCount = round(2.0f*radius*M_PI);
                float step = 1.0 / (float)compareCount;

                for (unsigned int t = 0; t < compareCount && !found; ++t) {
                    float theta = step*(float)t*360.0f;
                    glm::vec2 compareLocalCoord = glm::vec2(std::cos(theta), std::sin(theta))*radius;
                    glm::uvec2 compareCoord = sampleCoord + glm::uvec2(compareLocalCoord);
                    int comparePos = compareCoord.x + compareCoord.y*binaryAtlasWidth;
                    if (compareCoord.x >= 0 && compareCoord.x < binaryAtlasWidth&& compareCoord.y >= 0 && compareCoord.y < binaryAtlasHeight) {

                        unsigned char compareVal = buffer[comparePos];
                        if (compareVal != sampleVal ) {
                            float distance = sqrt(pow(compareLocalCoord.x, 2) + pow(compareLocalCoord.y, 2));
                            found = 1;
                            dist = std::min(distance * (1 - (sampleVal * 2)) , dist) ;
                        }
                    }
                }
                ++rad;
            }
            distanceSum += dist;
        }
    }

    float avgDistance = distanceSum / (float)(samplesPerOutPixel*samplesPerOutPixel);
    printf("pixel  %i  of  %i  has  %f  distance\n", outPixel, atlasPixelCount, avgDistance);
    unmappedBuffer[outPixel] = avgDistance;
    maxDistance = std::max(maxDistance, avgDistance);
    minDistance = std::min(minDistance, avgDistance);
}
minDistance *= -1.0;
float diff = maxDistance + minDistance;

//map all values between 0 and 255
for(unsigned int p = 0; p < atlasPixelCount; ++p) {
    float toMap = unmappedBuffer[p];
    float mappedDistance = 1.0f - (toMap + minDistance) / diff;
    atlas.buffer[p] = mappedDistance * 255;
}
//设置有符号距离场图集的大小
atlas.width=二进制AtlasWidth*pDistanceFieldResolution;
atlas.height=二进制AtlashHeight*pDistanceFieldResolution;
常量unsigned int atlasPixelCount=(atlas.width*atlas.height);
atlas.buffer.resize(atlasPixelCount);
//每个像素距离的临时缓冲区
std::向量未映射缓冲区;
unmappedBuffer.resize(atlasPixelCount);
//支持多采样
无符号int-samplesPerOutPixel=ceil(1.0/pDistanceFieldResolution);
//用于以后在0和1之间映射值
浮动最大距离=0.0;
浮动距离=0.0;
for(无符号int-outPixel=0;outPixel=0&&compareCoord.x=0&&compareCoord.y
此算法创建以下结果:

266x183输入纹理

未进行下采样的SDF结果(仍为266 x 183)

带下采样的SDF结果(106 x 73)

启用alpha测试时渲染结果(alpha大于0.5时通过):

无下采样、最近滤波

下采样、最近滤波

无下采样,线性滤波

下采样线性滤波

我的意思是,我正在达到目标,但实际上我希望得到如中所示的精确边缘。对于精确的边,我缺少什么


PS:my fragment着色器当前仅使用距离纹理值作为alpha值。(
color=vec4(1,1,1,距离);

它们使用更高的下采样率,距离变换看起来不够精确。有关快速准确的距离变换算法,请参阅。我只想感谢您在这里提供的宝贵资源!它们使用更高的下采样率,距离变换看起来不够精确。有关快速准确的距离变换算法,请参阅。我只想感谢您在这里提供的宝贵资源!