2012-12-13 14 views
13

Piszę aplikację OpenGL ES 2.0, która renderuje wyspę 3D. Mam już kod do generowania kopuły nieba wokół wyspy. Jest to półkula złożona z trójkątów, które nad wyspą mają punkt z w górę.Jak renderować przekonujący skydome?

Kopuła ma kilka bardzo prostych ruchomych chmur utworzonych przy użyciu tekstur szumów perlli nałożonych na siebie i poruszających się z różnymi prędkościami.

Ale w końcu muszę kopułę również render:

  • Sun (która śledzi po niebie) Księżyc (w tym faza)
  • Gwiazdki (w nocy)
  • dalekiego kraju jako statyczny tekstury
  • Różne kolory symulować noc, świt, zmierzch, dzień

muszę to zrobić dość sprawnie, ponieważ będzie to skończyć o n Android chociaż na razie działa w uprzęży testowej. Słońce, księżyc i gwiazdy będą na przykład teksturami, chociaż ich punkty mogą być nanoszone z odpowiednią dokładnością.

Mam już kod do generowania kopuły i kod do wykreślenia słońca z datą i godziną. Tak więc w większości są to shadery, których potrzebuję i do czego są dostarczane.

Czy istnieje przykład demonstrujący te rzeczy? Znalazłem mnóstwo, które robią podstawowe mapy sześcianu, lub ograniczone rzeczy, ale nic do poziomu wyrafinowania, którego potrzebuję. Oczywiście, ponieważ jest to OpenGL ES 2.0, trzeba to zrobić w shaderów.

Moduł cieniujący dla istniejącej kopuły nieba renderuje 2 warstwy szumu perlinowego w celu symulacji chmur. Tekstura owija się w sposób ciągły, dzięki czemu mogę obliczyć przesunięcie u oparte na kącie wierzchołka kopuły na płaszczyznę xy (przez podanie x i y na atan) i przesunięcie v przy użyciu wierzchołka kopuły z.

Wierzchołek shader pokazuje, jak to zrobić:

#ifdef GL_ES 
precision mediump float; 
precision mediump int; 
#endif 

attribute vec4 aVertex; 

uniform mat4 uPMVMatrix; 
uniform float uTime; 
uniform float uSkyDomeRadius; 

const float PI = 3.1415926535897932384626433832795; 

varying vec2 texCoord0, texCoord1; 

void main() 
{ 
    vec2 centre = vec2(600., 600.); 

    gl_Position = uPMVMatrix * aVertex; 

    float slow_time = uTime/100.; 

    vec2 dome_point = aVertex.xy - centre; 
    float tex_u = atan(dome_point.x, dome_point.y);///(.25 * PI); 
    float tex_v = aVertex.z/(uSkyDomeRadius * .5); 

    texCoord0 = vec2(tex_u/2.0 + slow_time, tex_v/2.0); 
    texCoord1 = vec2(tex_u + slow_time/2.0, tex_v); 
} 

Używam również czas, aby zrównoważyć u nieco każdą klatkę więc chmury poruszać. Działa to dobrze, chyba że atan przechodzi od -PI do PI i nagle wartości texCoord0 i texCoord1 interpolacji fragmentów cieniowania są oddzielone dużą odległością, która wsuwa interpolację.

Najlepszym sposobem, aby to opisać, jest to, że jeśli mam 16 trójkątów u podstawy, to interpolacja od 0/16 do 1/16 prac, 1/16 do 2/16 prac i tak dalej. Ale kiedy dojdę do 15/16 do 0/16 interpolator cofa się, a duża zmienność powoduje, że shader fragmentów powtarza teksturę w kółko na małej przestrzeni prowadzącej do pasków, jak pokazano.

Interpolation goes haywire as angle goes into reverse

Nie widzę żadnych sposobem na bezproblemowe widok 360 stopni myślę, że jedynym sposobem Zrobię to, jeśli obrócić całą kopułę tak szew jest zawsze za kamerą, ale może nadal pokaż, czy kamera wskazuje prosto do górnej części kopuły.

Przykład pracy ze źródłem byłby świetny, zwłaszcza jeśli rozwiązuje tego typu problemy.

+0

głupie pytanie, ale może być tex_x> PI lub BevynQ

+0

tex_x zawsze będzie między PI a PI bo atan zwraca te wartości. Mam 16 trójkątów u podstawy kopuły więc każda podstawa trójkąta przepisuje łuk 2pi/16 lub PI/8. So v0 może być 3/16-ty dookoła i v1 4/16 i tak tex_x interpoluje prawidłowo. Problem pojawia się, jeśli v0 to 15/16, a v1 to 0/16, a interpolacja jest całkowicie skręcona. Nie mogę wymyślić, jak to naprawić, więc spekuluję, że będę musiał obrócić kopułę, aby szew był zawsze za kamerą i zrównoważyć wszystko, co wykonam w równoważnej ilości. – locka

+0

Uaktualniłem to pytanie, aby wyjaśnić to i zmieniłem nazwę tex_x i tex_y jako tex_u i tex_v – locka

Odpowiedz

3

Problem polega na tym, że używasz tych samych wierzchołków pod kątem 0 ° i 360 °. Masz teraz trójkąt, w którym pierwszy wierzchołek ma współrzędne tekstury 15/16, 0, a drugi ma 0, 0 zamiast 1,0.Aby to naprawić, musisz otworzyć kulę, aby mieć parę wierzchołków w tej samej pozycji przestrzennej, jedną dla 0 ° i jedną dla 360 °. W ten sposób dwa wierzchołki mogą mieć różne współrzędne tekstury i nie będzie żadnych zakłóceń tekstur.

Aby obrócić je trzeba użyć trybów zawijania, upewnij się, że opakowanie jest ustawione tekstury powtarzać. Jeśli go nie zmieniłeś, powinien on zostać poprawnie skonfigurowany, ale można go ustawić za pomocą funkcji glTexParameter, parametrami są GL_TEXTURE_WRAP_S i GL_TEXTURE_WRAP_T, a wartość musi wynosić GL_REPEAT. Następnie, jeśli wartość tekstury wynosi> 1, nie będzie się zawijać, ale powtórzy teksturę. Teraz musisz tylko móc powiedzieć wierzchołkom na początku sfery (dla wierzchołków 0 °) od wierzchołków (dla wierzchołków w 360 °), aby móc poprawić tex_u, prawdopodobnie potrzebujesz dodatkowego atrybutu dla tego .

+0

Dzięki, dam ci wolę. Mam świadomość, że problem polega na tym, że kąt skutecznie zawija się do zera, ale zobaczę, czy uda mi się wygenerować skydome w jakiś sposób, który kompensuje to, jak sugerujesz. – locka

Powiązane problemy