2012-05-23 21 views
5

Mam aplikację na Androida z wykorzystaniem OpenGL ES 2.0. Muszę narysować 10 linii z tablicy, z których każda jest opisana przez punkt początkowy i punkt końcowy. Tak więc istnieje 10 linii = 20 punktów = 60 wartości pływaka. Żaden z punktów nie jest połączony, więc każda para punktów w tablicy jest niezwiązana z pozostałymi, dlatego rysuję za pomocą GL_LINES.Jak korzystać z modułu cieniującego do kolorowania linii narysowanych za pomocą GL_LINES i OpenGL ES 2.0

Rysuję je przez wprowadzenie wartości do bufora pływaka i wywołanie kodu pomocnika takiego:

public void drawLines(FloatBuffer vertexBuffer, float lineWidth, 
     int numPoints, float colour[]) { 
    GLES20.glLineWidth(lineWidth); 
    drawShape(vertexBuffer, GLES20.GL_LINES, numPoints, colour); 
} 

protected void drawShape(FloatBuffer vertexBuffer, int drawType, 
     int numPoints, float colour[]) { 
    // ... set shader ... 
    GLES20.glDrawArrays(drawType, 0, numPoints); 
} 

W drawLines potrzebny bufor float (60 pływający), A szerokości linii, liczbę punktów (20) i tablicę wartości kolorów 4 float. Nie pokazałem kodu ustawienia shadera, ale zasadniczo eksponuje on zmienną koloru na jednolitą wartość koloru.

Fragment shadera, który odbiera uColour po prostu podłącza go prosto do wyjścia.

/* Fragment */ 
precision mediump float; 

uniform vec4 uColour; 
uniform float uTime; 

void main() { 
    gl_FragColor = uColour; 
} 

Moduł cieniujący wierzchołek:

uniform mat4 uMVPMatrix; 

attribute vec4 vPosition; 

void main() { 
    gl_Position = uMVPMatrix * vPosition; 
} 

Ale teraz chcę zrobić coś innego. Chcę, aby każda linia w moim buforze miała inny kolor. Kolory są funkcją pozycji linii w tablicy. Chcę odcień linii początkowej białej, ostatniego ciemnoszarego i linii między gradacją między dwoma, np. #ffffff, #eeeeee, #ddddd itd.

Mogę oczywiście narysować każdą linię indywidualnie, każdorazowo podłączając nową wartość do koloru, ale to jest nieefektywne. Nie chcę wywoływać GL 10 razy, gdybym mógł go wywołać raz i zmodyfikować wartość w module cieniującym za każdym razem.

Być może mógłbym zadeklarować jednolitą wartość o nazwie uVertexCount w moim procesorze wierzchołków? Przed losowaniem ustawię uVertexCount na 0 i za każdym razem, gdy wywoływany jest vertex shader, zwiększam tę wartość. Moduł cieniujący może określić indeks linii, patrząc na wartość uVertexCount. Następnie można interpolować wartość koloru między pewną wartością początkową i końcową lub innymi sposobami. Ale to zależy, czy każda linia lub punkt jest traktowana jako prymitywna, czy cała tablica linii jest pojedynczą prymitywą.

Czy to możliwe? Nie wiem, ile razy werteks cieniowania jest wywoływany na moduł cieniujący fragmentu. Połączenia są przeplatane w taki sposób, jak to zrobić to opłacalne, czyli wierzchołek 0, wierzchołek 1, x * fragment Vertex 2 Vertex 3, x * fragment itp

Czy ktoś wie o jakimś rozsądnym przykładowy kod, który może zademonstrować koncepcję lub wskazać mi jakiś inny sposób robienia czegoś podobnego?

+0

Dlaczego nie używać koloru jako atrybut? Dodaj informacje o kolorze w swoim VertexBuffer. – pearcoding

+0

Mogłabym dodać go jako atrybut, ale nadal potrzebuję znać indeks punktu/linii w module cieniującym fragment, aby wiedzieć, który kolor z tego atrybutu powinienem użyć. np. jeśli przekazałem tablicę 10 kolorów jako atrybut, w jaki sposób mój shader fragmentu wie, którego z nich powinien używać? – locka

+0

nie jest wykonywane automatycznie ...potrzebujesz indeksu, jeśli masz jednolitą tablicę, ale nie wtedy, gdy masz atrybut. Jeden atrybut jest połączony tylko z jednym wierzchołkiem. Więc każdy z twoich wierzchołków ma pozycję i kolor. – pearcoding

Odpowiedz

6

Dodaj informacje o kolorach do swojego Bufora Vertexbuffer (Floatbuffer) i użyj atrybutu w swoim module cieniującym.

Przykład VertexBuffer:

uniform mat4 uMVPMatrix; 

attribute vec4 vPosition; 
attribute vec3 vColor; 

varying vec3 color; 

void main() { 
    gl_Position = uMVPMatrix * vPosition; 
    color = vColor; 
} 

Przykład fragmentshader:

precision mediump float; 

varying vec3 color; 

void main() { 
    gl_FragColor = color; 
} 
+0

Sugerujesz, że używam glDrawElements zamiast glDrawArray tutaj w jakiś sposób, aby wcisnąć vColor do wektorowego shadera? Czy kolor kończy się na interpolacji lub cokolwiek z tego, czy musiałbym podać ten sam kolor do punktu początkowego/końcowego, aby upewnić się, że zmienna wartość się nie zmienia? Spróbuję to zrobić dziś wieczorem, żeby zobaczyć, jak sobie radzę. – locka

+2

Myślę, że mam to teraz. Muszę powiązać glVertexAttribPointer/glEnableVertexAttribArray z tablicą float dla kolorów. Prawdopodobnie muszę podwoić kolory dla każdego końca linii, ale to powinno być dość proste. Wezmę aktualizację, gdy zdobędę się gdzieś z tym. – locka

+0

+1 Tak to jest właściwa droga: D – pearcoding