XNA의 둥근 모서리?


10

XNA로 렌더링 된 사각형에서 원형 (줄무늬)을 통해 둥근 모서리를 만들 수있는 방법이 있습니까? UI를 기존보다 조금 더 멋지게 만들고 싶습니다. 텍스처가 너무 많지 않고 코드가 유연 해지기를 원합니다.


기본적으로 : 선에 하나의 텍스처를 사용하고 선의 둥근 끝에 하나의 텍스처를 사용하십시오. 이 두 텍스처를 적절하게 사용하는 스프라이트를 회전하고 크기를 조정합니다.
Olhovsky

답변:


8

프리미티브를 렌더링하고 둥근 모서리를 만들 수있는 셰이더를 만들 수 있습니다.
둥근 사각형을 그릴 수있는 의사 코드의 간단한 픽셀 쉐이더는 다음과 같습니다.

xDist = abs(x-0.5)
yDist = abs(y-0.5)
xD = xDist*xDist*4
yD = yDist*yDist*4
alpha = floor((1-xD)*(1-yD)*5)

이 픽셀 쉐이더의 결과 :

여기에 이미지 설명을 입력하십시오

셰이더를 사용하면 정말 멋진 UI, 심지어 애니메이션 UI를 만들 수 있습니다.

간단한 픽셀 쉐이더를 프로토 타이핑하는 것은 EvalDraw 프로그램입니다.


5

이를 수행하는 또 다른 방법은 '버튼 스트레치'( '박스 스트레치'또는 '나인 패치'라고도 함)를 사용하는 것입니다. 기본적으로 9 개의 부분으로 구성된 이미지를 만듭니다.

버튼 리소스

해당 버튼을 원하는 크기로 그리려면 각 조각 (위에서 아래로, 왼쪽에서 오른쪽으로)을 그립니다.

  1. 대상 사각형의 왼쪽 상단에 크기를 조정하여 그립니다.
  2. width - ((1) + (2)).Width대상 사각형의 상단에 가로로 ( )를 축척 하여 왼쪽 오프셋을 (1) 너비로 그립니다.
  3. 대상 사각형의 오른쪽 상단에 크기를 조정하여 그립니다.
  4. height - ((1) + (2)).Height대상 사각형의 왼쪽에서 (1)의 높이로 상단 오프셋을 사용하여 수직으로 스케일 을 그립니다.
  5. (1)의 너비와 높이로 오프셋되어 (2의 너비와 높이 (4)의) 양방향으로 배율을 그립니다.
  6. 대상 사각형의 오른쪽에 세로로 축척 ((4)와 동일한 높이)을 그려 (1)의 높이로 오프셋합니다.
  7. 대상 사각형의 왼쪽 하단에 크기를 조정하여 그립니다.
  8. 대상 사각형의 아래쪽에 (1) 너비로 오프셋 된 수평으로 크기를 조정합니다 ((2)와 동일한 높이).
  9. 대상 사각형의 오른쪽 하단에 크기를 조정하여 그립니다.

버튼을 보면 (2), (5) 및 (7)이 수평으로 스케일링되는지 (기본적으로 직선이기 때문에) 중요하지 않음을 알 수 있습니다. 동일한 방식으로, (4), (5) 및 (6)은 이미지의 품질에 영향을 미치지 않으면 서 수직으로 스케일링 될 수있다.


예, 이것은 질문에 직접 대답하지는 않지만 누군가가 여전히 유용하다고 생각할 수 있습니다.
조나단 디킨슨

4
그것은 9 패치라고하며 실제로 텍스처로 원하는 모양을 만들 수 있기 때문에 실제로 셰이더를 사용하는 것보다 훨씬 유연하고 저렴합니다. 그런 다음 모든 위젯 이미지를 단일 텍스처 아틀라스에 넣을 수 있습니다. 대부분의 GUI는 이런 식으로합니다.
Elisée

0

다음은 "9 패치"접근 방식에 대한 코드입니다.

public static class SpriteBatchExtensions
{
    public static void DrawRoundedRect(this SpriteBatch spriteBatch, Rectangle destinationRectangle, 
        Texture2D texture, int border, Color color)
    {
        // Top left
        spriteBatch.Draw(
            texture, 
            new Rectangle(destinationRectangle.Location, new Point(border)), 
            new Rectangle(0, 0, border, border), 
            color);

        // Top
        spriteBatch.Draw(
            texture, 
            new Rectangle(destinationRectangle.Location + new Point(border, 0), 
                new Point(destinationRectangle.Width - border * 2, border)), 
            new Rectangle(border, 0, texture.Width - border * 2, border), 
            color);

        // Top right
        spriteBatch.Draw(
            texture, 
            new Rectangle(destinationRectangle.Location + new Point(destinationRectangle.Width - border, 0), new Point(border)), 
            new Rectangle(texture.Width - border, 0, border, border), 
            color);

        // Middle left
        spriteBatch.Draw(
            texture, 
            new Rectangle(destinationRectangle.Location + new Point(0, border), new Point(border, destinationRectangle.Height - border * 2)), 
            new Rectangle(0, border, border, texture.Height - border * 2), 
            color);

        // Middle
        spriteBatch.Draw(
            texture, 
            new Rectangle(destinationRectangle.Location + new Point(border), destinationRectangle.Size - new Point(border * 2)), 
            new Rectangle(border, border, texture.Width - border * 2, texture.Height - border * 2), 
            color);

        // Middle right
        spriteBatch.Draw(
            texture, 
            new Rectangle(destinationRectangle.Location + new Point(destinationRectangle.Width - border, border), 
                new Point(border, destinationRectangle.Height - border * 2)), 
            new Rectangle(texture.Width - border, border, border, texture.Height - border * 2), 
            color);

        // Bottom left
        spriteBatch.Draw(
            texture, 
            new Rectangle(destinationRectangle.Location + new Point(0, destinationRectangle.Height - border), new Point(border)), 
            new Rectangle(0, texture.Height - border, border, border), 
            color);

        // Bottom
        spriteBatch.Draw(
            texture, 
            new Rectangle(destinationRectangle.Location + new Point(border, destinationRectangle.Height - border), 
                new Point(destinationRectangle.Width - border * 2, border)), 
            new Rectangle(border, texture.Height - border, texture.Width - border * 2, border), 
            color);

        // Bottom right
        spriteBatch.Draw(
            texture, 
            new Rectangle(destinationRectangle.Location + destinationRectangle.Size - new Point(border), new Point(border)), 
            new Rectangle(texture.Width - border, texture.Height - border, border, border), 
            color);
    }
}

다음과 같이 호출됩니다.

spriteBatch.DrawRoundedRect(
    dest, // The coordinates of the Rectangle to be drawn
    rectangleTexture, // Texture for the whole rounded rectangle
    16, // Distance from the edges of the texture to the "middle" patch
    Color.OrangeRed);

이것은 나를 위해 작동하지 않습니다 ... 나는 단지 일반 사각형을 얻습니다. 나는 그것을 사용하는 방법이다Texture2D _texture = new Texture2D(GraphicsDevice, 1, 1); _texture.SetData(new Color[] { Color.Blue }); SpriteBatch sb = new SpriteBatch(GraphicsDevice); sb.Begin(); //sb.Draw(_texture, new Rectangle(100, 100, 100, 100), Color.White); sb.DrawRoundedRect(_texture, new Rectangle(100, 100, 100, 100), Color.Pink, 16); sb.End();
레오나르도 Seccia

텍스처는 단지 하나의 파란색 픽셀이며,이 방법은 둥근 모서리가 텍스처의 일부라고 가정합니다.
sdgfsdh

죄송합니다 - 아주 새로운 플랫폼으로 ... 이렇게 빨리 나에게 다시 점점 주셔서 감사합니다
레오나르도 Seccia을
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.