void Painter::renderSDF(SymbolBucket& bucket,
                        const RenderTile& tile,
                        float sdfFontSize,
                        std::array<float, 2> texsize,
                        SDFShader& sdfShader,
                        void (SymbolBucket::*drawSDF)(SDFShader&, gl::ObjectStore&, bool),

                        // Layout
                        AlignmentType rotationAlignment,
                        AlignmentType pitchAlignment,
                        float layoutSize,

                        // Paint
                        float opacity,
                        Color color,
                        Color haloColor,
                        float haloWidth,
                        float haloBlur,
                        std::array<float, 2> translate,
                        TranslateAnchorType translateAnchor,
                        float paintSize)
{
    mat4 vtxMatrix = tile.translatedMatrix(translate, translateAnchor, state);

    // If layerStyle.size > bucket.info.fontSize then labels may collide
    float fontSize = paintSize;
    float fontScale = fontSize / sdfFontSize;

    bool rotateWithMap = rotationAlignment == AlignmentType::Map;
    bool pitchWithMap = pitchAlignment == AlignmentType::Map;

    std::array<float, 2> extrudeScale;
    float gammaScale;

    if (pitchWithMap) {
        gammaScale = 1.0 / std::cos(state.getPitch());
        extrudeScale.fill(tile.id.pixelsToTileUnits(1, state.getZoom()) * fontScale);
    } else {
        gammaScale = 1.0;
        extrudeScale = {{
            pixelsToGLUnits[0] * fontScale * state.getAltitude(),
            pixelsToGLUnits[1] * fontScale * state.getAltitude()
        }};
    }

    config.program = sdfShader.getID();
    sdfShader.u_matrix = vtxMatrix;
    sdfShader.u_extrude_scale = extrudeScale;
    sdfShader.u_texsize = texsize;
    sdfShader.u_rotate_with_map = rotateWithMap;
    sdfShader.u_pitch_with_map = pitchWithMap;
    sdfShader.u_texture = 0;
    sdfShader.u_pitch = state.getPitch() * util::DEG2RAD;
    sdfShader.u_bearing = -1.0f * state.getAngle();
    sdfShader.u_aspect_ratio = (state.getWidth() * 1.0f) / (state.getHeight() * 1.0f);

    // adjust min/max zooms for variable font sies
    float zoomAdjust = std::log(fontSize / layoutSize) / std::log(2);

    sdfShader.u_zoom = (state.getZoom() - zoomAdjust) * 10; // current zoom level

    frameHistory.bind(store, config, 1);
    sdfShader.u_fadetexture = 1;

    // The default gamma value has to be adjust for the current pixelratio so that we're not
    // drawing blurry font on retina screens.
    const float gamma = 0.105 * sdfFontSize / fontSize / frame.pixelRatio;

    const float sdfPx = 8.0f;
    const float blurOffset = 1.19f;
    const float haloOffset = 6.0f;

    // We're drawing in the translucent pass which is bottom-to-top, so we need
    // to draw the halo first.
    if (haloColor.a > 0.0f && haloWidth > 0.0f) {
        sdfShader.u_gamma = (haloBlur * blurOffset / fontScale / sdfPx + gamma) * gammaScale;
        sdfShader.u_color = haloColor;
        sdfShader.u_opacity = opacity;
        sdfShader.u_buffer = (haloOffset - haloWidth / fontScale) / sdfPx;

        setDepthSublayer(0);
        (bucket.*drawSDF)(sdfShader, store, isOverdraw());
    }

    // Then, we draw the text/icon over the halo
    if (color.a > 0.0f) {
        sdfShader.u_gamma = gamma * gammaScale;
        sdfShader.u_color = color;
        sdfShader.u_opacity = opacity;
        sdfShader.u_buffer = (256.0f - 64.0f) / 256.0f;

        setDepthSublayer(1);
        (bucket.*drawSDF)(sdfShader, store, isOverdraw());
    }
}
Esempio n. 2
0
void Painter::renderSDF(SymbolBucket &bucket,
                        const UnwrappedTileID &tileID,
                        const mat4 &matrix,
                        float sdfFontSize,
                        std::array<float, 2> texsize,
                        SDFShader& sdfShader,
                        void (SymbolBucket::*drawSDF)(SDFShader&, gl::ObjectStore&),

                        // Layout
                        RotationAlignmentType rotationAlignment,
                        float layoutSize,

                        // Paint
                        float opacity,
                        Color color,
                        Color haloColor,
                        float haloWidth,
                        float haloBlur,
                        std::array<float, 2> translate,
                        TranslateAnchorType translateAnchor,
                        float paintSize)
{
    mat4 vtxMatrix = translatedMatrix(matrix, translate, tileID, translateAnchor);

    // If layerStyle.size > bucket.info.fontSize then labels may collide
    float fontSize = paintSize;
    float fontScale = fontSize / sdfFontSize;

    float scale = fontScale;
    std::array<float, 2> exScale = extrudeScale;
    bool alignedWithMap = rotationAlignment == RotationAlignmentType::Map;
    float gammaScale = 1.0f;

    if (alignedWithMap) {
        scale *= tileID.pixelsToTileUnits(1, state.getZoom());
        exScale.fill(scale);
        gammaScale /= std::cos(state.getPitch());
    } else {
        exScale = {{ exScale[0] * scale, exScale[1] * scale }};
    }

    config.program = sdfShader.getID();
    sdfShader.u_matrix = vtxMatrix;
    sdfShader.u_extrude_scale = exScale;
    sdfShader.u_texsize = texsize;
    sdfShader.u_skewed = alignedWithMap;
    sdfShader.u_texture = 0;

    // adjust min/max zooms for variable font sies
    float zoomAdjust = std::log(fontSize / layoutSize) / std::log(2);

    sdfShader.u_zoom = (state.getZoom() - zoomAdjust) * 10; // current zoom level

    config.activeTexture = GL_TEXTURE1;
    frameHistory.bind(store);
    sdfShader.u_fadetexture = 1;

    // The default gamma value has to be adjust for the current pixelratio so that we're not
    // drawing blurry font on retina screens.
    const float gamma = 0.105 * sdfFontSize / fontSize / frame.pixelRatio;

    const float sdfPx = 8.0f;
    const float blurOffset = 1.19f;
    const float haloOffset = 6.0f;

    // We're drawing in the translucent pass which is bottom-to-top, so we need
    // to draw the halo first.
    if (haloColor[3] > 0.0f && haloWidth > 0.0f) {
        sdfShader.u_gamma = (haloBlur * blurOffset / fontScale / sdfPx + gamma) * gammaScale;
        sdfShader.u_color = haloColor;
        sdfShader.u_opacity = opacity;
        sdfShader.u_buffer = (haloOffset - haloWidth / fontScale) / sdfPx;

        setDepthSublayer(0);
        (bucket.*drawSDF)(sdfShader, store);
    }

    // Then, we draw the text/icon over the halo
    if (color[3] > 0.0f) {
        sdfShader.u_gamma = gamma * gammaScale;
        sdfShader.u_color = color;
        sdfShader.u_opacity = opacity;
        sdfShader.u_buffer = (256.0f - 64.0f) / 256.0f;

        setDepthSublayer(1);
        (bucket.*drawSDF)(sdfShader, store);
    }
}