Sudut membulat di XNA?

10

Apakah ada cara saya bisa membuat sudut bulat pada persegi panjang yang diberikan dalam XNA melalui primitif (garis-strip)? Saya ingin membuat UI saya sedikit lebih mewah daripada yang sudah ada, dan saya ingin kode menjadi fleksibel, tanpa terlalu banyak tekstur yang terlibat.

Mathias Lykkegaard Lorenzen
sumber
Pada dasarnya: Gunakan satu tekstur untuk garis, satu tekstur untuk ujung-ujung garis. Putar dan skala sprite yang menggunakan dua tekstur ini dengan tepat.
Olhovsky

Jawaban:

8

Anda dapat membuat primitif Anda, dan membuat shader yang dapat membuat sudut-sudut membulat ini.
Berikut ini adalah shader piksel sederhana dalam pseudocode yang dapat menggambar kotak bulat:

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)

Hasil dari shader piksel ini:

masukkan deskripsi gambar di sini

Jika Anda menggunakan shader, Anda dapat membuat UI yang benar-benar mewah, bahkan yang animasi.

Bagi saya hebat untuk prototipe pixel shaders sederhana adalah program EvalDraw

piotrek
sumber
5

Cara lain untuk melakukan ini adalah dengan menggunakan 'peregangan tombol' (juga disebut 'peregangan kotak' atau 'sembilan-tambalan'). Pada dasarnya Anda membuat gambar yang terdiri dari 9 bagian:

Sumber Daya Tombol

Untuk menggambar tombol itu dalam ukuran berapa pun, Anda menggambar setiap bagian (dari atas ke bawah, kiri ke kanan):

  1. Gambar tanpa skala di kiri atas persegi panjang tujuan.
  2. Gambarlah skala secara horizontal (dengan width - ((1) + (2)).Width) di bagian atas persegi panjang tujuan, dengan offset kiri dengan lebar (1).
  3. Gambar tanpa skala di kanan atas persegi panjang tujuan.
  4. Gambarlah diskalakan secara vertikal (dengan height - ((1) + (2)).Height) di sebelah kiri persegi panjang tujuan, dengan bagian atas diimbangi oleh ketinggian (1).
  5. Gambarlah diskalakan di kedua arah (dengan lebar (2) dan tinggi (4)), diimbangi dengan lebar dan tinggi (1).
  6. Gambar berskala vertikal (tinggi sama dengan (4)) di sebelah kanan persegi panjang tujuan, diimbangi dengan ketinggian (1).
  7. Gambar tanpa skala di kiri bawah persegi panjang tujuan.
  8. Gambar skala secara horizontal (sama dengan (2)) di bagian bawah persegi panjang tujuan, diimbangi dengan lebar (1).
  9. Gambar tanpa skala di kanan bawah persegi panjang tujuan.

Jika Anda melihat tombol Anda akan melihat bahwa tidak masalah jika (2), (5) dan (7) diskalakan secara horizontal (karena pada dasarnya itu adalah garis lurus); dengan cara yang sama (4), (5) dan (6) dapat diskalakan secara vertikal tanpa mempengaruhi kualitas gambar.

Jonathan Dickinson
sumber
Ya, ini tidak menjawab pertanyaan secara langsung - tetapi seseorang mungkin masih menganggapnya berguna.
Jonathan Dickinson
4
Ini disebut sembilan-tambalan dan sebenarnya jauh lebih fleksibel (dan lebih murah!) Daripada menggunakan shader karena Anda dapat membuatnya terlihat sesuai keinginan Anda dengan tekstur. Anda kemudian dapat meletakkan semua gambar widget Anda dalam satu atlas tekstur tunggal. Kebanyakan GUI melakukannya dengan cara ini.
Elisée
0

Berikut adalah kode untuk pendekatan "sembilan-patch":

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);
    }
}

Itu dipanggil sebagai:

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);
sdgfsdh
sumber
ini tidak bekerja untuk saya ... Saya hanya mendapatkan persegi panjang normal. Ini adalah bagaimana saya menggunakannyaTexture2D _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();
Leonardo Seccia
Tekstur Anda hanya satu piksel biru, pendekatan ini mengasumsikan sudut membulat adalah bagian dari tekstur Anda.
sdgfsdh
maaf - sangat baru di platform ... terima kasih telah kembali ke saya begitu cepat
Leonardo Seccia