← 과제 목록

[과제] 2주차 Basic Programming 박태춘

@tcpark11
  • #과제

#74

2022,2026 두 차례의 월드컵을 통해 메시의 큰 팬이 되었습니다.

이를 기념해 ThorVG 의 Drawing API 를 사용해 메시의 아르헨티나 국가대표 유니폼을 그려보기로 합니다.

[결과물]

Messi10 image

바로가기

[상세]

<아르헨티나 유니폼>

아르헨티나 유니폼의 형상과 특유의 하얀색~하늘색의 Gradient 를 구현했습니다.

` // --------------------------------------------------------------------- // Argentina Uniform // ---------------------------------------------------------------------

    auto bg = tvg::Shape::gen();
    bg->appendRect(0, 0, w, h);
    bg->fill(250, 250, 250);
    canvas->add(bg);

    // Argentina sky-blue stripes
    const uint8_t skyR = 120;
    const uint8_t skyG = 205;
    const uint8_t skyB = 255;

    float stripe = w / 7.0f;

    for (int i = 0; i < 7; i++) {

        if (i % 2 == 0) continue;

        auto rect = tvg::Shape::gen();

        rect->appendRect(i * stripe, 0, stripe, h);

        rect->fill(skyR, skyG, skyB);

        canvas->add(rect);
    }

    float side = w * 0.18f;
    float center = w * 0.08f;

    tvg::Fill::ColorStop stops[4] = {
        {0.0f, 100,190,245,255},
        {0.25f,145,220,255,255},
        {0.75f,145,220,255,255},
        {1.0f,100,190,245,255}
    };

    auto stripe1 = tvg::Shape::gen();
    stripe1->appendRect(w*0.08f, 0, side, h);
    auto grad1 = tvg::LinearGradient::gen();

    grad1->linear(
        w*0.08f,
        0,
        w*0.08f + side,
        0
    );

    grad1->colorStops(stops,5);

    stripe1->fill(grad1);
            canvas->add(stripe1);

            auto stripe2 = tvg::Shape::gen();
            stripe2->appendRect(w*0.46f, 0, center, h);
    auto grad2 = tvg::LinearGradient::gen();

    grad2->linear(
        w*0.46f,
        0,
        w*0.46f + center,
        0
    );

    grad2->colorStops(stops,5);

    stripe2->fill(grad2);
            canvas->add(stripe2);

            auto stripe3 = tvg::Shape::gen();
            stripe3->appendRect(w*0.74f, 0, side, h);
    auto grad3 = tvg::LinearGradient::gen();

    grad3->linear(
        w*0.74f,
        0,
        w*0.74f + side,
        0
    );

    grad3->colorStops(stops,5);

    stripe3->fill(grad3);
    canvas->add(stripe3);

    // left shoulder 
    auto leftShoulder = tvg::Shape::gen();

    leftShoulder->moveTo(0,0);
    leftShoulder->lineTo(w*0.18f,0);
    leftShoulder->lineTo(0,h*0.12f);
    leftShoulder->close();

    leftShoulder->fill(235,235,235);

    canvas->add(leftShoulder);

    // right shoulder
    auto rightShoulder = tvg::Shape::gen();

    rightShoulder->moveTo(w,0);
    rightShoulder->lineTo(w,h*0.12f);
    rightShoulder->lineTo(w*0.82f,0);
    rightShoulder->close();

    rightShoulder->fill(235,235,235);

    canvas->add(rightShoulder);

    // neck
    auto neck = tvg::Shape::gen();

    neck->appendRect(w*0.44f,0,w*0.12f,10);

    neck->fill(30,30,30);

    canvas->add(neck);`

<유니폼 효과>

유니폼 전체를 덮는 반투명한 세로 방향의 Gradient Overlay를 추가하여, 윗부분은 약간 밝고 아랫부분은 약간 어둡게 하여 입체감을 부여하고자 했습니다.

` // ---------------------------------------------------------- // Uniform Effect // ----------------------------------------------------------

    auto overlay = tvg::Shape::gen();

    overlay->appendRect(0,0,w,h);

    auto shade = tvg::LinearGradient::gen();

    shade->linear(0,0,0,h);

    tvg::Fill::ColorStop s[3] = {

        {0.0f,255,255,255,45},

        {0.55f,255,255,255,0},

        {1.0f,120,120,120,35}
    };

    shade->colorStops(s,3);

    overlay->fill(shade);

    canvas->add(overlay);`

<배지>

월드컵 우승팀을 상징하는 배지를 그려보았습니다. 원래는 월드컵 트로피 형상이어야 하는데 이게 디테일하게 그리기는 좀 어려워서 간단히 금색 배지로 갈음했습니다.

` // ---------------------------------------------------------- // Champion Badge // ----------------------------------------------------------

    const float badgeW = 46;
    const float badgeH = 62;

    float badgeX = w * 0.5f - badgeW * 0.5f;
    float badgeY = 40;


    // Shadow

    auto shadow = tvg::Shape::gen();

    shadow->appendRect(
        badgeX+2,
        badgeY+2,
        badgeW,
        badgeH,
        8,
        8
    );

    shadow->fill(0,0,0,40);

    canvas->add(shadow);


    // Outer

    auto badge = tvg::Shape::gen();

    badge->appendRect(
        badgeX,
        badgeY,
        badgeW,
        badgeH,
        8,
        8
    );

    badge->fill(212,175,55);

    canvas->add(badge);


    // Inner

    auto inner = tvg::Shape::gen();

    inner->appendRect(
        badgeX+5,
        badgeY+5,
        badgeW-10,
        badgeH-10,
        6,
        6
    );

    inner->fill(245,220,90);

    canvas->add(inner);


    // White circle

    auto circle = tvg::Shape::gen();

    circle->appendCircle(
        badgeX+badgeW/2,
        badgeY+18,
        5,
        5
    );

    circle->fill(255,255,255);

    canvas->add(circle);`

< Messi 10 >

메시의 이름과 백넘버를 그렸습니다. 글씨에 그림자 효과도 적용하여 조금 더 깊이감을 주었습니다.

`
//----------------------------- // “Messi 10” //-----------------------------

    // Load font
    if (!tvgexam::verify(tvg::Text::load(EXAMPLE_DIR "/font/DejaVuSans-Bold.ttf")))
        return false;

    //-----------------------------
    // "messi"
    //-----------------------------

    auto name = tvg::Text::gen();
    name->font("DejaVuSans-Bold");
    name->size(60);
    name->text("messi");
    name->fill(0, 0, 0);

    //-----------------------------
    // "10"
    //-----------------------------
    auto number = tvg::Text::gen();
    number->font("DejaVuSans-Bold");
    number->size(100);
    number->text("10");
    number->fill(0, 0, 0);

    // Measure Font Size 
    float x, y, nameW, nameH;
    float nx, ny, numW, numH;

    name->bounds(&x, &y, &nameW, &nameH);
    number->bounds(&nx, &ny, &numW, &numH);

    // Center Alignment
    const float spacing = 45.0f;

    float totalHeight = nameH + spacing + numH;

    float startY = (h - totalHeight) * 0.5f;

    float nameX = (w - nameW) * 0.5f - x;
    float nameY = startY - y;

    float numX = (w - numW) * 0.5f - nx;
    float numY = startY + nameH + spacing - ny;

    name->translate(nameX, nameY);
    number->translate(numX, numY);

    //-----------------------------
    // "Messi" Shadow Efect 
    //-----------------------------

    auto nameShadow = tvg::Text::gen();

    nameShadow->font("DejaVuSans-Bold");
    nameShadow->size(60);
    nameShadow->text("messi");
    nameShadow->fill(90,90,90);
    nameShadow->translate(nameX + 2, nameY + 2);

    //-----------------------------
    // "10" Shadow Efect 
    //-----------------------------

    auto numShadow = tvg::Text::gen();

    numShadow->font("DejaVuSans-Bold");
    numShadow->size(100);
    numShadow->text("10");
    numShadow->fill(90,90,90);
    numShadow->translate(numX + 4, numY + 4);



    canvas->add(nameShadow);
    canvas->add(numShadow);
    canvas->add(name);
    canvas->add(number); `

댓글

Discussion 원문