Parça gölgelendiricisi, bir pikselin rengi için hangi değişkeni kullanacağını nasıl bilir?


83

Çok sayıda farklı parça gölgelendiricisi görüyorum,

Ve hepsi "dış renk" için farklı bir değişken kullanır (bu durumda flatColor). Peki OpenGL ne yapmaya çalıştığınızı nasıl biliyor?

Sanırım bu işe yarıyor çünkü flatColortanımlanmış tek değişken out, ancak daha fazla outdeğişken eklemenize izin var değil mi? Yoksa bu sadece çökecek mi?


Aslında, bir test olarak şunu çalıştırdım:

Kullanmış olsam xda iyi çalıştı y.


Ayrıca önceden tanımlanmış bir var gl_FragColor. Aradaki fark nedir ve neden insanlar genellikle kendi değişkenlerini kullanmakta ısrar ediyor?

Yanıtlar:


143

Ayrıca, önceden tanımlanmış bir gl_FragColor'a sahibiz.

Bununla başlayalım. Hayır, önceden tanımlı değilsingl_FragColor . Bu çekirdek OpenGL 3.1 ve üzeri sürümlerden kaldırıldı. Uyumluluğu kullanmadığınız sürece (bu durumda, 3.30 gölgelendiriciniz #version 330 compatibilityen üstte yazmalıdır ), bunu asla kullanmamalısınız.

Şimdi, kullanıcı tanımlı parça gölgelendirici çıktılarına geri dönün. Ama önce hızlı bir benzetme.

Köşe gölgelendiricilerinde girdilerinizin nasıl olduğunu hatırlıyor musunuz? Ve bu girişler, nitelik endeksleri köşe size aktarmak sayıları temsil glVertexAttribPointerve glEnableVertexAttribArraybenzeri ve? Hangi girdinin hangi nitelikten çekileceğini siz belirlersiniz. GLSL 3.30'da şu sözdizimini kullanırsınız:

Bu, colorköşe gölgelendiricisi girdisinin öznitelik konumu 2'den gelmesini sağlar. 3.30'dan önce (veya ARB_explicit_attrib_location olmadan), bunu glBindAttrbLocationbağlamadan önce açıkça ayarlamanız veya öznitelik dizini için programı sorgulamanız gerekir glGetAttribLocation. Açıkça bir öznitelik konumu sağlamazsanız, GLSL keyfi olarak bir konum atayacaktır (yani: uygulama tanımlı bir şekilde).

Gölgelendiricide ayarlamak neredeyse her zaman daha iyi bir seçenektir.

Her durumda, parça gölgelendirici çıktıları neredeyse tamamen aynı şekilde çalışır. Parça gölgelendiricileri , çerçeve arabelleğindeki birden çok arabelleğe eşlenen birden çok çıktı rengine yazabilir . Bu nedenle, hangi çıktının hangi parça çıktı rengine gideceğini belirtmeniz gerekir.

Bu işlem, parça çıktı konumu değeriyle başlar. Köşe gölgelendirici girdi konumlarına çok benzer şekilde ayarlanır:

API işlevleri de vardır glBindFragDataLocationve glGetFragDataLocationbenzer olan, glBindAttribLocationve glGetAttribLocation.

Herhangi bir açık atama yapmazsanız, uygulamalar genellikle çıkış değişkenlerinizden birini konum 0'a atar. Ancak, OpenGL standardı bu davranışı gerektirmez , bu nedenle ona da bağlı olmamanız gerekir.

Şimdi adil olmak, programınız olmalıdır başarısız Eğer farklı çıkış yerleri alamadım iki çıkışa kullanıldığında bağlantı. Muhtemelen olan şey, derleyicinizin yazmadığınız dosyayı optimize etmesiydi, bu yüzden bağlayıcı hatalarını kontrol etme zamanı geldiğinde bunu unutmuştu.


4
Keşke + 1'den fazlasını verebilseydim. Muhteşem cevap. Parça çıktı konumlarının nasıl çalıştığını merak ediyordum. :)
kevintodisco

Ahh .. yani gl_FragColor, hangi arabelleğe yazacağınızı seçmeniz için size daha fazla esneklik vermeyi tercih ettiler? Mantıklı. Tekrar teşekkürler!
mpen

3
@Mark: "Kullanımdan kaldırma", "yine de kullanabilirsiniz, ancak sonraki sürümlerde kaldırılabilir" anlamına gelir. "Kaldırıldı", kaldırılmış anlamına gelir . Bir fark var. GL 3.0'da kullanımdan kaldırılan işaret 3.1'de kaldırıldı (birkaç şey dışında).
Nicol Bolas

3
@NicolBolas: "GL 3.3 ve üstü (bu önceki sürümlerden bir değişikliktir) hepsini 0 konumuna atayacaktır". Bunun şartname tarafından nerede garanti edildiğini merak ediyorum. 3.3 "Bir program bağlandığında, belirtilmiş [...] veya gölgelendirici metni içinde açıkça belirlenmiş bir bağlama olmaksızın değişen değişkenler, GL tarafından otomatik olarak parça renklerine ve indekslerine bağlanacaktır. Tüm bu atamalar, sıfır.". Son cümle 3.2'de bulunmamaktadır. Bununla birlikte, indeks renk numarasına değil, yalnızca çift kaynaklı karıştırma indeksine (3.3'e eklenmiştir) atıfta bulunur .
derhass

1
Teşekkürler @NicolBolas, harika cevap! Bu yüzden henüz tam olarak anlamadım ve sadece "sorgusuz sualsiz" yapmak istiyorum. Gölgelendiricilerimizde, her layout (location = 0) out vec4 outColorzaman bağlı olanı çizerken belirtiriz (çoğu zaman "ekran", bir FBO değil). Öyleyse varsayılan olarak, glDrawBuffers kullanarak bir FBO'yu (veya başka bir tamponu) bağlamazsak ve belirtirsek location = 0, ekrana her zaman doğru şekilde çizilir mi?
AzP

9

Bunu GLSL_ES_3.10 bağlantısını kullanan OpenGLES 3.1 için belirtmek istiyorum :

§4.4.2

[Parça gölgelendiricide] yalnızca tek bir çıktı varsa, konumun belirtilmesine gerek yoktur, bu durumda varsayılan olarak sıfır olur.

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.