Grafik tabanlı bir malzeme sisteminde, çeşitli girdi ve çıktı türlerini nasıl destekleyebilirim?


11

resim açıklamasını buraya girin

Ben gibi malzeme sistemleri nasıl başımı etrafında sarmak için çalışıyorum bu , bu uygulanmaktadır. Bu güçlü ve kullanıcı dostu, grafik benzeri sistemler , programcıların ve programcı olmayanların hızla gölgelendirici oluşturmasına izin verme yöntemi olarak nispeten yaygın görünmektedir . Ancak, grafik programlama konusundaki sınırlı deneyimimden, nasıl çalıştıklarından tam olarak emin değilim.


Arka fon:

Bu nedenle, daha önce basit OpenGL oluşturma sistemlerini programladığımda , genellikle el ile oluşturduğum statik GLSL dosyalarından gölgelendiricileri yükleyen, derleyen ve bağlayan bir Material sınıfı oluştururum. Genellikle bu sınıfı GLSL tekdüzen değişkenlerine erişmek için basit bir sarıcı olarak oluştururum. Basit bir örnek olarak, bir doku geçmek için ekstra tekdüze bir Texture2D içeren temel bir köşe gölgelendiricisine ve parça gölgelendiricisine sahip olduğumu düşünün. Malzeme sınıfım bu iki gölgelendiriciyi bir malzemeye yükler ve derler ve bu noktadan sonra bu gölgelendiricinin Texture2D üniformasını okumak / yazmak için basit bir arabirim ortaya koyar.

Bu sistemi biraz daha esnek hale getirmek için, genellikle herhangi bir ad / tür üniformasını geçirmeye çalışmamı sağlayacak şekilde yazıyorum [yani: SetUniform_Vec4 ("AmbientColor", colorVec4); bu, AmbientColor üniformasını, malzemede bu üniforma varsa "colorVec4" adlı belirli bir 4d vektörüne ayarlayacaktır.] .

class Material
{
    private:
       int shaderID;
       string vertShaderPath;
       string fragSahderPath;

       void loadShaderFiles(); //load shaders from files at internal paths.
       void buildMaterial(); //link, compile, buffer with OpenGL, etc.      

    public:
        void SetGenericUniform( string uniformName, int param );
        void SetGenericUniform( string uniformName, float param );
        void SetGenericUniform( string uniformName, vec4 param );
        //overrides for various types, etc...

        int GetUniform( string uniformName );
        float GetUniform( string uniformName );
        vec4 GetUniform( string uniformName );
        //etc...

        //ctor, dtor, etc., omitted for clarity..
}

Bu işe yarıyor, ancak Material sınıfının müşterisinin sadece iman üzerindeki üniformalara erişmesi gerektiği için kötü bir sistem gibi geliyor - kullanıcı, her maddi nesnede bulunan üniformalardan biraz haberdar olmalı, çünkü GLSL adıyla iletin. Sistemle çalışan sadece 1-2 kişi olduğunda çok büyük bir anlaşma değil, ancak bu sistemin çok iyi ölçekleneceğini hayal edemiyorum ve bir sonraki OpenGL oluşturma sistemini programlama girişimimi yapmadan önce seviyelendirmek istiyorum biraz yukarı.


Soru:

Şimdiye kadar buradayım, bu yüzden diğer render motorlarının malzeme sistemlerini nasıl ele aldığını araştırmaya çalışıyorum.

Bu düğüm tabanlı yaklaşım harika ve modern motorlarda ve araçlarda kullanıcı dostu malzeme sistemleri oluşturmak için son derece yaygın bir sistem gibi görünüyor. Söyleyebileceğimden , her düğümün malzemenizin bazı gölgelendirici yönünü temsil ettiği ve her yolun aralarındaki bir tür ilişkiyi temsil ettiği bir grafik veri yapısına dayanıyorlar .

Söyleyebileceğim kadarıyla, bu tür bir sistemi uygulamak, çeşitli alt sınıflara (TextureNode, FloatNode, LerpNode, vb.) Sahip bir MaterialNode sınıfı kadar basit olurdu. Her MaterialNode alt sınıfının MaterialConnections'a sahip olacağı yer.

class MaterialConnection
{
    MatNode_Out * fromNode;
    MatNode_In * toNode;
}

class LerpNode : MaterialNode
{
    MatNode_In x;
    MatNode_In y;
    MatNode_In alpha;

    MatNode_Out result;
}

Bu çok basit bir fikir, ama bu sistemin birkaç yönünün nasıl çalışacağından biraz emin değilim:

1.) Unreal Engine 4'ün kullandığı çeşitli 'Malzeme İfadeleri'ne (düğümleri) bakarsanız, her birinin çeşitli tiplerde giriş ve çıkış bağlantılarına sahip olduğunu göreceksiniz. Bazı düğümlerin çıkışları, bazıları çıkış vektörü2, bazıları çıkış vektörü4 vb. Çeşitli giriş ve çıkış türlerini destekleyebilmeleri için yukarıdaki düğümleri ve bağlantıları nasıl geliştirebilirim? MatNode_Out'u MatNode_Out_Float ve MatNode_Out_Vec4 (ve benzeri) ile alt sınıflandırma akıllıca bir seçim olur mu?

2.) Son olarak, bu tür bir sistem GLSL gölgelendiricileri ile nasıl ilişkilidir? Yine UE4'e bakıldığında (ve benzer şekilde yukarıda bağlanmış diğer sistemler için), kullanıcının sonunda bir miktar malzeme düğümünü, gölgelendirici parametrelerini (temel renk, metallik, parlaklık, emisyon, vb.) Temsil eden çeşitli parametrelere sahip büyük bir düğüme takması gerekir. . Orijinal varsayımım, UE4'ün çeşitli üniformaları olan bir çeşit sabit kodlu 'ana gölgelendirici' olduğu ve kullanıcının 'malzemesinde' yaptığı her şey, düğümlerini ' ana düğüm '.

Ancak, UE4 belgeleri şunları belirtir:

"Her düğüm, belirli bir görevi gerçekleştirmek üzere belirlenmiş bir HLSL kodu snippet'i içerir. Bu, bir Malzeme oluştururken görsel komut dosyası oluşturma yoluyla HLSL kodu oluşturduğunuz anlamına gelir."

Bu doğruysa, bu sistem gerçek bir gölgelendirici komut dosyası oluşturur mu? Bu tam olarak nasıl çalışıyor?


Yanıtlar:


10

UE4'ün özel durumu hakkında çok az bilgiyle değil, genel teknikle ilgili bilgimin en iyisine cevap vermeye çalışacağım.

Grafik tabanlı materyaller, kodu kendiniz yazmak kadar programlamadır. Kodda arka planı olmayan insanlar için öyle hissettirmiyor, bu da daha kolay görünmesini sağlıyor. Böylece, bir tasarımcı bir "Ekle" düğümü bağladığında, temel olarak add (değer1, değer2) yazar ve çıktıyı başka bir şeye bağlar. Bu, her bir düğümün bir işlev çağrısı veya sadece basit talimatlar ile HLSL kodu üreteceği anlamına gelir.

Sonunda, malzeme grafiğini kullanmak, bazı yaygın yararlı şeyler yapan önceden tanımlanmış işlevler kitaplığıyla ham gölgelendiricileri programlamak gibidir ve UE4 de bunu yapar. Gölgelendirici derleyicisinin alacağı ve uygulanabilir olduğunda son gölgelendirici kaynağına enjekte edeceği bir gölgelendirici kodu kitaplığına sahiptir.

UE4 durumunda, HLSL'ye dönüştürüldüğünü iddia ederse, HLSL bayt kodunu GLSL bayt koduna dönüştürebilen bir dönüştürücü aracı kullandıklarını varsayıyorum, bu yüzden GL platformlarında kullanılabilir. Ancak diğer kütüphanelerde sadece grafiği okuyacak ve gerekli gölgelendirme dili kaynaklarını doğrudan oluşturacak birden fazla gölgelendirici derleyicisi vardır.

Malzeme grafiği, platform özelliklerinden soyutlamak ve bir sanat yönü açısından neyin önemli olduğuna odaklanmak için de güzel bir yoldur. Bir dile ve çok daha yüksek bir seviyeye bağlı olmadığı için, hedef platform için optimize edilmesi ve gölgelendiriciye ışık kullanımı gibi diğer kodları dinamik olarak enjekte etmesi daha kolaydır.

1) Şimdi sorularınızı daha doğrudan cevaplamak için, böyle bir sistemi tasarlamak için veriye dayalı bir yaklaşımınız olmalıdır. Çok düz yapılarda ve hatta bir metin dosyasında tanımlanabilecek düz bir biçim bulun. Özünde, her grafik bir tür, bir girdi ve çıktı kümesiyle bir düğüm dizisi olmalı ve grafik bağlantılarının açık olduğundan emin olmak için bu alanların her birinin yerel bir link_id'i olmalıdır. Ayrıca, bu alanların her biri, alanın desteklediği şeye ek yapılandırmaya sahip olabilir (örneğin, hangi veri türlerinin desteklendiği).

Bu yaklaşımla, bir düğümün alanını kolayca (float | double) olarak tanımlayabilir ve sınıf hiyerarşileri veya mühendisliği olmadan türü bağlantılardan çıkartabilir veya bir türü zorlayabilirsiniz. Bu grafik veri yapısını istediğiniz kadar katı veya esnek olarak tasarlamak size kalmıştır. İhtiyacınız olan tek şey, kod üreticisinin belirsizliğe sahip olmaması ve bu nedenle yapmak istediğiniz şeyi yanlış işlemesi için yeterli bilgiye sahip olmasıdır. Önemli olan, temel veri yapısı düzeyinde, onu esnek tutmanız ve tek başına bir malzeme tanımlama görevini çözmeye odaklanmış olmanızdır.

"Bir malzeme tanımla" dediğimde, geometriğin kendisinin ötesinde bir örgü yüzeyin tanımlanmasından bahsediyorum. Bu, yüzeyin yönünü yapılandırmak, bir yükseklik haritasına yer değiştirme eklemek, normalleri piksel başına normallerle bozmak, fiziksel tabanlı parametreleri değiştirmek, BRDF'leri değiştirmek vb. İçin ek köşe özellikleri kullanmaktır. HDR, tonemapping, arayüz animasyonu, hafif kullanım veya gölgelendiricilerde yapılan diğer birçok şeyi tanımlamak istemezsiniz.

2) Daha sonra bu veri yapısını hareket ettirmek ve bilgilerini okuyarak bir dizi değişkenleri birleştirmek ve bunları önceden yapılmış işlevleri kullanarak ve aydınlatma ve diğer etkileri hesaplayan kodu enjekte etmek, oluşturucunun gölgelendirici üreticisine bağlıdır. Sadece gölgelendiricilerin sadece farklı grafik API'larından değil, aynı zamanda farklı oluşturucular arasında (ertelenmiş bir render - fayans tabanlı ve ileri oluşturucunun hepsinin çalışması için farklı gölgelendiriciler gerektirdiğini) unutmayın ve bunun gibi bir malzeme sistemi ile, kötülerden soyutlayabilirsiniz. düşük seviyeli katman ve sadece yüzeyi tanımlamaya odaklanın.´

UE4 için, bahsettiğiniz son çıkış düğümü için bir şeyler listesi buldular, ki bu eski ve modern oyunlardaki yüzeylerin% 99'unu açıklıyor. Bu parametre setini onlarca yıl geliştirdiler ve Unreal motorunun bugüne kadar ürettiği çılgınca oyunlarla kanıtladılar. Bu nedenle, işleri gerçek dışı gibi yaparsanız iyi olacaksınız.

Özetlemek için, sadece her grafiği işlemek için bir .material dosyası öneririm. Geliştirme sırasında, hata ayıklamak için belki de metin tabanlı bir biçim içerir ve daha sonra serbest bırakılmak üzere paketlenir veya ikili dosyaya derlenir. Her .material, tıpkı bir SQL veritabanı gibi N düğümleri ve N bağlantıları tarafından oluşturulacaktır. Her düğümde, girişleri veya çıkışları, türler çıkarılırsa, vb. İçin bir ad ve bazı bayraklar kabul edilen N alanları olacaktır. Yüklenen malzemeyi tutmak için çalışma zamanı veri yapısı aynı düz ve basit olacaktır, bu nedenle editör kolayca adapte ve dosyaya geri kaydedebilirsiniz.

Ve son gölgelendirici nesli için gerçek ağır kaldırmayı bırakın, ki bu gerçekten en zor kısımdır. Güzel kısım, malzemenizin oluşturma platformuna agnostik kalmasıdır, teorik olarak, malzemeyi uygun gölgelendirme dilinde temsil ettiğiniz sürece herhangi bir oluşturma tekniği ve API ile çalışacaktır.

Cevabımda ek ayrıntılara veya herhangi bir düzeltmeye ihtiyacınız varsa bana bildirin, tüm metnin genel görünümünü kaybettim.


Bu kadar ayrıntılı ve mükemmel bir cevap yazdığınız için size teşekkür edemem. Buradan nereye gitmem gerektiği konusunda harika bir fikrim var gibi hissediyorum! Teşekkürler!
MrKatSwordfish

1
Sorun değil dostum, daha fazla yardıma ihtiyacınız olursa bana mesaj atmaktan çekinmeyin. Aslında kendi araçlarım için eşdeğer bir şey üzerinde çalışıyorum, bu yüzden düşünce ticareti yapmak istiyorsanız misafirim olun! İyi günler: D
Grimshaw
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.