SORU
9 Mayıs 2011, PAZARTESİ


Derinlik, siyah çizgiler taklit dönüşüm dokular (düz nesneleri 3D olarak çizilmiş) rastgele görünür

Yukarıdan aşağıya RPG kullanarak PAZARLAR geliştiriyoruz. Son zamanlarda haritaları görüntülemek için kod yazarken bir aksilik çarptık. Harita, yukarıdan aşağıya çizim normal bir dönüşüm matrisi ile görüntülemek, her şey iyi olacak gibi görünüyor. Ne zaman kullanarak bir düz olmayan dönüşüm matrisi gibi sıkma üst veya alt kısmına taklit derinliği, siyah çizgiler (satırlar zaman üst veya alt, sütun sola veya sağa sıkılmış) bu hareket ne zaman kamera değişiklikleri konumu, görünür. Hareket ve yerleştirme rastgele gibi görünüyor. (Resim daha aşağı sağladı.)

Arka plan bilgileri

Haritalar fayans içerir. Özgün doku fayans 32 x 32 piksel içerir. 2 üçgenler oluşturarak ve bu üçgenlerin orijinal doku parçası görüntüleyerek fayans çizeriz. Bir shader bizim için bunu yapar. Üçgenlerin üç katman var. İlk yarı opak ve kısmi saydam tüm taşlar tüm opak fayans ve tüm piksel opak, yarı opak ve kısmi saydam karolar ve piksel tüm çizeriz. Bu güzel (ama biz kayan nokta faktörüyle çekim yaparken, bazen renk karışık çizgiler çini satır ve/veya sütunlar arasında) çalışır.

Renderstates

Tüm taşlar aynı rasterizerState kullanıyoruz ve katı ya da yarı-şeffaf kiremit çizerken iki arasında geçiş yapar.

_rasterizerState = new RasterizerState();
_rasterizerState.CullMode = CullMode.CullCounterClockwiseFace;

_solidDepthState = new DepthStencilState();
_solidDepthState.DepthBufferEnable = true;
_solidDepthState.DepthBufferWriteEnable = true;

_alphaDepthState = new DepthStencilState();
_alphaDepthState.DepthBufferEnable = true;
_alphaDepthState.DepthBufferWriteEnable = false;

Gölgede aşağıdaki gibi SpriteBlendMode kurduk

İlk katı Kat 1 kullanır

AlphaBlendEnable = False; 
SrcBlend = One; 
DestBlend = Zero; 

Katı ve şeffaf diğer tüm katmanları (üstü çizilmiş) kullanın

AlphaBlendEnable = True; 
SrcBlend = SrcAlpha;
DestBlend = InvSrcAlpha; 

Diğer gölgeleme de bunu kullan. SpriteFonts SpriteBatch varsayılan ayar kullanılır kullanır.

Doku Oluşturdu

Bazı taşlar anında oluşturulur ve dosyaya kaydedilebilir. Dosyayı göster yüklendiğinde yüklenir. Bu şöyle: RenderTarget bir oluşturulan kullanılarak yapılır

RenderTarget2D rt = new RenderTarget2D(sb.GraphicsDevice, 768, 1792, false, 
    SurfaceFormat.Color, DepthFormat.None);
    sb.GraphicsDevice.SetRenderTarget(rt);

Oluşturulan dosyayı ve artık RenderTarget üzerinde olacak çünkü cihaz sıfırlar zaman kaybetmek istemem () kayıtlı yüklenir. Mipmap oluşturma kullanarak denedim, ama bir spritesheet. Fayans yerleştirildiği hakkında bilgi yok, mipmap oluşturma işe yaramaz ve bu sorunu çözmedi.

Köşeler

Biz her pozisyon döngü. Kayan henüz puan, ama bir pozisyon Vector3 (Float3).

for (UInt16 x = 0; x < _width;  x  )
{
    for (UInt16 y = 0; y < _heigth; y  )
    {
        [...]
        position.z = priority; // this is a byte 0-5

Karolar, aşağıdaki kodu konumlandırmak için kullanılır:

tilePosition.X = position.X;
tilePosition.Y = position.Y   position.Z;
tilePosition.Z = position.Z;

Bildiğiniz gibi, 32 bit, hassasiyet için 24 bit ile yüzer. Z en fazla bit değeri 8 bit (5 = 00000101). X ve Y için maksimum değerleri 16 bit olabilir. 24 bit. Hiçbir şey yüzen puan açısından yanlış gidebileceğini düşündüm.

this.Position = tilePosition;

Köşe ayarladığınızda, aşağıdaki gibi hepsi aynı kiremit pozisyonda)

Vector3[] offsets  = new Vector3[] { Vector3.Zero, Vector3.Right, 
    Vector3.Right   (this.IsVertical ? Vector3.Forward : Vector3.Up), 
    (this.IsVertical ? Vector3.Forward : Vector3.Up) };
Vector2[] texOffset = new Vector2[] { Vector2.Zero, Vector2.UnitX, 
    Vector2.One, Vector2.UnitY };

for (int i = 0; i < 4; i  )
{
    SetVertex(out arr[start   i]);
    arr[start   i].vertexPosition = Position   offsets[i];

    if (this.Tiles[0] != null)
        arr[start   i].texturePos1  = texOffset[i] * this.Tiles[0].TextureWidth;
    if (this.Tiles[1] != null)
        arr[start   i].texturePos2  = texOffset[i] * this.Tiles[1].TextureWidth;
    if (this.Tiles[2] != null)
        arr[start   i].texturePos3  = texOffset[i] * this.Tiles[2].TextureWidth;
}

Shader

Gölgelendirici animasyonlu fayans ve Fayans statik çizebilirsiniz. Her ikisi de aşağıdaki sampler devlet kullanın:

sampler2D staticTilesSampler = sampler_state { 
    texture = <staticTiles> ; magfilter = POINT; minfilter = POINT; 
    mipfilter = POINT; AddressU = clamp; AddressV = clamp;};

Gölgelendiricinin farklı sampler Birleşik Devletleri, Biz de bizim kod yok set yok.

Her, biz alfa değeri siyah piksel yok) aşağıdaki satırı kullanarak klip geçirir

clip(color.a - alpha)

Alfa katı Kat 1 ve 1neredeyseBaşka bir katman için 0. Bu alfa bir kısmını ise, alt tabaka ne bilemeyiz çünkü) sürece çizilmiş olması anlamına gelir.

Kamera

Kullandığımız kamera için mimik arama tepeden aşağı fayans, yapma gibi görünen düz, kullanarak z değeri için onlara katman dış katman veri (3 kat değil, her zaman doğru sipariş). Bu da gayet iyi çalışıyor. Kamera güncellemeleri dönüşüm matrisi. Böyle garip bir yapısı var neden merak ediyorsanız.AddChange - kodu Tamponlu Çift (bu da çalışır). Dönüşüm matrisi aşağıdaki gibi oluşturulur

// First get the position we will be looking at. Zoom is normally 32
Single x = (Single)Math.Round((newPosition.X   newShakeOffset.X) * 
    this.Zoom) / this.Zoom;
Single y = (Single)Math.Round((newPosition.Y   newShakeOffset.Y) * 
    this.Zoom) / this.Zoom;

// Translation
Matrix translation = Matrix.CreateTranslation(-x, -y, 0);

// Projection
Matrix obliqueProjection = new Matrix(1, 0, 0, 0,
                                      0, 1, 1, 0,
                                      0, -1, 0, 0,
                                      0, 0, 0, 1);

Matrix taper = Matrix.Identity; 

// Base it of center screen
Matrix orthographic = Matrix.CreateOrthographicOffCenter(
    -_resolution.X / this.Zoom / 2, 
     _resolution.X / this.Zoom / 2, 
     _resolution.Y / this.Zoom / 2, 
    -_resolution.Y / this.Zoom / 2, 
    -10000, 10000);

// Shake rotation. This works fine       
Matrix shakeRotation = Matrix.CreateRotationZ(
    newShakeOffset.Z > 0.01 ? newShakeOffset.Z / 20 : 0);

// Projection is used in Draw/Render
this.AddChange(() => { 
    this.Projection = translation * obliqueProjection * 
    orthographic * taper * shakeRotation; }); 

Akıl ve Akış

Karo veri 3 kat vardır. Her karo IsSemiTransparent ile tanımlanır. Bir karo olduğunda IsSemiTransparent, sonra IsSemiTransparent çizilmiş olması gerekiyor. Karo veri SplattedTile bir örnek üzerinde yüklü olduğunda yığılmış. Eğer katman kiremit veri boşsa bile, SplattedTile katman ilk katman, (verilen en az bir katman kiremit veri var) çini veri olacak. Nedeni Z-buffer eğer arkasında sağlam bir piksel olabilir hiçbir beri sırayla çizilmiş, onlar ile uyum için ne olduğunu bilmiyor.

Katmanları z bir değeri YOK, tek tek çini veri vardır. Zemin karo, Priority = 0. Aynı döşemeleri ile 34 ** katman (çizim sırası) ve sayede donukluk (yarı saydam, opak sonra) sipariş edilebilir. Farklı bir öncelik ile taşlar kendi önceliklerine göre çekilecek.

İlk katı katman hedef piksele sahip, DestinationBlend.Zero bunu aldım. Ayrıca alphablend için bir şey olmadığından AlphaBlending, ihtiyacı yok. Diğer katmanları (5, 2 katı, 3 şeffaf) zaten ve buna göre uyum renk verileri ihtiyaç olduğunda çizilmiş olabilir.

6 geçirir yineleme önce, projection matrix ayarlanır. Hayır konik kullanırken, bu çalışıyor. Bir konik kullanırken değil.

Sorun

Konik uygulayarak biraz daha derinlik taklit etmek için, bazı matrisi kullanarak istiyoruz. Bazı değerler denedik ama bu bir örnek:

new Matrix(1, 0, 0, 0,
           0, 1, 0, 0.1f,
           0, 0, 1, 0,
           0, 0, 0, 1);

Ekran (yükseklik değeri 0, tüm düz malzeme ile her şeyi) sıkılmış olacak. Alt y (ekran üzeri), fazla sıkılmış. Bu gerçekten çalışıyor, ama şimdi rastgele siyah çizgiler hemen hemen her yerde görünür. Birkaç fayans dışlamak gibi görünüyor, ama bu ilişki göremiyorum. Bir şey aradeğerleme veya mipmaps ile bir ilgisi olabileceğini düşünüyoruz.

Ve burada neden söz ettiğimi göstermek için bir görüntü: Screenshot with lines.

Kiremit değil etkilenen alt tabaka üzerinde statik fayans gibi görünüyor.Ancak, bu konuda en şeffaf fayans diğer grafik eserler göstermek. Satır satır sadece silinmiş, bu yüzden () özlüyorlar.Ne için bir ipucu olduğunu düşünüyorum, çünkü bu metin işaretledim.dikeyçizgiler Linear 39 *koyarsanız görünür.

Burada bir resim (oyun zoom) yakınlaştırma veya 3 katman 2 çini obje gösteriyor Screenshot with lines, zoomed in

Biz zaten denedik

  • Point Linear mipfilter
  • Orijinal dokular üzerinde GenerateMipMaps ayarı
  • Oluşturulan dokular (RenderTarget gerçek bayrak kurucu) GenerateMipMaps ayarı
  • Mipmap oluşturma açma (sadece mipmapping a spritesheet olduğum için uzaklaştırıldığında daha fazla eser verdi.
  • Çizim katman 2 ve 3 (Bu aslında TÜM taşlar siyah çizgiler var yapar)
  • DepthBufferEnable = false
  • SrcBlend = One; DestBlend = Zero; tüm katı katmanları ayarı
  • * DestBlend = InvSrcAlpha; *50 tüm katı katmanları ayarı
  • Saydam tabaka çizim (çizgiler hala orada).
  • clip(opacity) shader kaldırılıyor. Bu sadece bazı satırlar kaldırır. Bu da araştırıyoruz.
  • Msdn, stackoverflow aynı sorun için arama ve google (hiç şans) kullanarak.

Kimse bu sorunu kabul ediyor mu? Son bir not, fayans çizdikten SONRA SpriteBatch çağrı yapıyoruz ve avatarlar (yükseklik ^ oldukları için sorun yok. Shader başka bir kullanım 0). Bu bizim sampler state Geri Al? Ya da...?

CEVAP
10 Mayıs 2011, Salı


Son resmin altındaki taşa bak - kumlu-renkli çizgiler geçiyor. Muhtemelen, önce kum, sonra da üzerine Kaya çizim.

Bu "siyah çizgiler" dokular aracılığıyla, ama doku parçaları çizilmiş. çizilmiş ibaret olmadığını söylüyor Sen dikey streç zaman olur bu yana, bu neredeyse kesinlikle yeni Piksel piksel eski bir eşleme oluşturmak demektir, değerleri, yeni doku arasındakileri interpolasyon olmadan.

Örneğin, eşleme kullanarak (x,y) --> (x, 2y) puan (0,0) --> (0,0), (0,1) --> (0,2) ve (0,2) --> (0, 4) gibi eşleştirilmiş olacak. Kaynak doku ve sayı yok (0,1) (0,3) göster dikkat edin. Bu arka plan yayılması neden olur. Eğer horizonally germek için değiştirirseniz, dikey çizgiler göreceksiniz eminim.

Yapmak için ne gerekir başka yolu göster: hedef doku, her piksel için verilen, kaynak görüntü dönüşüm yukarıda. tersini kullanarak değerini bulmak Muhtemelen değerler eklemek istiyorum, böylece kesirli değerler piksel koordinatlarını alacaksınız.

JAY ile hiç aşina değilim, ama muhtemelen elle daha bunu yapmak için daha uygun bir yol var.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Amazon Web Services

    Amazon Web S

    8 NİSAN 2009
  • BroadCity

    BroadCity

    10 ŞUBAT 2010
  • Learn Math Tutorials

    Learn Math T

    20 Kasım 2011